You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by dp...@apache.org on 2017/05/19 19:52:02 UTC
[2/2] logging-log4net git commit: An initial commit of the rolling
file appender ng implementation [LOG4NET-367]
An initial commit of the rolling file appender ng implementation [LOG4NET-367]
Project: http://git-wip-us.apache.org/repos/asf/logging-log4net/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4net/commit/829b2eb5
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4net/tree/829b2eb5
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4net/diff/829b2eb5
Branch: refs/heads/feature/RollingFileAppender-NG
Commit: 829b2eb59d14caa0bcbfeeea34c65154741b9b4c
Parents: cde6b69
Author: Dominik Psenner <dp...@apache.org>
Authored: Fri May 19 21:47:32 2017 +0200
Committer: Dominik Psenner <dp...@apache.org>
Committed: Fri May 19 21:47:32 2017 +0200
----------------------------------------------------------------------
src/Appender/Rolling/CronRollingCondition.cs | 230 +++++++++++++++++++
src/Appender/Rolling/IRollingCondition.cs | 38 +++
src/Appender/Rolling/IRollingStrategy.cs | 36 +++
src/Appender/Rolling/IndexRollingStrategy.cs | 77 +++++++
src/Appender/RollingFileAppenderNG.cs | 152 ++++++++++++
.../Rolling/CronRollingConditionTest.cs | 45 ++++
.../Rolling/IndexRollingStrategyTest.cs | 83 +++++++
tests/src/log4net.Tests.vs2012.csproj | 2 +
8 files changed, 663 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/829b2eb5/src/Appender/Rolling/CronRollingCondition.cs
----------------------------------------------------------------------
diff --git a/src/Appender/Rolling/CronRollingCondition.cs b/src/Appender/Rolling/CronRollingCondition.cs
new file mode 100644
index 0000000..f355648
--- /dev/null
+++ b/src/Appender/Rolling/CronRollingCondition.cs
@@ -0,0 +1,230 @@
+#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;
+
+namespace log4net.Appender.Rolling
+{
+ /// <summary>
+ /// A implementation of the <see cref="IRollingCondition"/> interface that rolls
+ /// the file cronologically.
+ /// </summary>
+ /// <author>Dominik Psenner</author>
+ public class CronRollingCondition : IRollingCondition
+ {
+ #region Public Instance Constructors
+
+ public CronRollingCondition()
+ : this("*", "*", "*", "*", "*")
+ {
+ }
+
+ public CronRollingCondition(string dow, string month, string day, string hour, string minute)
+ {
+ Dow = TryParse(dow);
+ Month = TryParse(month);
+ Day = TryParse(day);
+ Hour = TryParse(hour);
+ Minute = TryParse(minute);
+ }
+
+ #endregion
+
+ #region Protected Instance Properties
+
+ protected Tuple<int?, MatchType> Dow { get; private set; }
+ protected Tuple<int?, MatchType> Month { get; private set; }
+ protected Tuple<int?, MatchType> Day { get; private set; }
+ protected Tuple<int?, MatchType> Hour { get; private set; }
+ protected Tuple<int?, MatchType> Minute { get; private set; }
+
+ #endregion
+
+ #region Private Instance Properties
+
+ private ulong last_rolled = 0;
+
+ #endregion
+
+ #region Protected Inner Classes
+
+ protected enum MatchType
+ {
+ Nothing,
+ Exact,
+ Remainder,
+ }
+
+ #endregion
+
+ #region Protected Static Methods
+
+ /// <summary>
+ /// This method parses a string to match any of these:
+ /// i
+ /// *
+ /// */i
+ /// </summary>
+ /// <param name="input"></param>
+ /// <returns></returns>
+ static protected Tuple<int?, MatchType> TryParse(string input)
+ {
+ // trim input and strip empty spaces
+ string inputParsed = input.Trim().Replace(" ", "").Replace("\t", "");
+
+ // match a remainder: */c
+ if (inputParsed.StartsWith("*/") || inputParsed.StartsWith(@"*\"))
+ {
+ // strip first two chars
+ inputParsed = inputParsed.Substring(2);
+ // parse the remainder
+ int i = -1;
+ if (int.TryParse(inputParsed, out i))
+ {
+ return Tuple.Create<int?, MatchType>(i, MatchType.Remainder);
+ }
+ }
+ else if (inputParsed.StartsWith("*")) // match anything: *
+ {
+ return Tuple.Create<int?, MatchType>(null, MatchType.Nothing);
+ }
+ else // match one specific numer: i
+ {
+ int i = -1;
+ if (int.TryParse(inputParsed, out i))
+ {
+ return Tuple.Create<int?, MatchType>(i, MatchType.Exact);
+ }
+ }
+
+ // throw exception by default
+ throw new FormatException(string.Format("The input string '{0}' could not be parsed to a valid format.", input));
+ }
+
+ #endregion
+
+ #region Implementation of IRollingCondition
+
+ public bool IsMet(string file)
+ {
+ return IsMet(DateTime.Now);
+ }
+
+ private static ulong GetUniqueIndex(DateTime now)
+ {
+ ulong result = (ulong)now.DayOfWeek;
+ result <<= 3;
+ result += (ulong)now.Month;
+ result <<= 4;
+ result += (ulong)now.Day;
+ result <<= 5;
+ result += (ulong)now.Hour;
+ result <<= 5;
+ result += (ulong)now.Minute;
+ return result;
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ public bool IsMet(DateTime now)
+ {
+ Console.WriteLine("test {0}", now);
+ // check only every minute
+ // we can skip the check as we checked this minute already
+ // and if we don't we may run into the situation to roll a file twice
+ if (GetUniqueIndex(now) == last_rolled)
+ {
+ Console.WriteLine(" skipped");
+ return false;
+ }
+ if (!IsMet(Dow, (int)now.DayOfWeek))
+ {
+ return false;
+ }
+ if (!IsMet(Month, now.Month))
+ {
+ return false;
+ }
+ if (!IsMet(Day, now.Day))
+ {
+ return false;
+ }
+ if (!IsMet(Hour, now.Hour))
+ {
+ return false;
+ }
+ if (!IsMet(Minute, now.Minute))
+ {
+ return false;
+ }
+
+ last_rolled = GetUniqueIndex(now);
+ return true;
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private bool IsMet(Tuple<int?, MatchType> match, int item)
+ {
+ switch (match.Item2)
+ {
+ case MatchType.Exact:
+ Console.WriteLine(" {0} != {1} == {2}", match.Item1.Value, item, match.Item1.Value != item);
+ if (match.Item1.Value != item)
+ {
+ return false;
+ }
+ break;
+ case MatchType.Remainder:
+ // special case: */0, the division through 0 is undefined; this match should pass
+ if (match.Item1.Value == 0)
+ {
+ Console.WriteLine("{0} % 0 == 0", item);
+ return false;
+ }
+ else
+ {
+ Console.WriteLine(" {0} % {1} == {2}", item, match.Item1.Value, item % match.Item1.Value);
+ if (item % match.Item1.Value != 0)
+ {
+ return false;
+ }
+ }
+ break;
+ }
+ return true;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Converts the given rolling condition to a nicely formatted string representation.
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString()
+ {
+ return string.Format("{0} {1} {2} {3} {4}", Dow, Month, Day, Hour, Minute);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/829b2eb5/src/Appender/Rolling/IRollingCondition.cs
----------------------------------------------------------------------
diff --git a/src/Appender/Rolling/IRollingCondition.cs b/src/Appender/Rolling/IRollingCondition.cs
new file mode 100644
index 0000000..e7777b6
--- /dev/null
+++ b/src/Appender/Rolling/IRollingCondition.cs
@@ -0,0 +1,38 @@
+#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;
+
+namespace log4net.Appender.Rolling
+{
+ /// <summary>
+ /// The interface definition of a rolling condition.
+ /// </summary>
+ /// <author>Dominik Psenner</author>
+ public interface IRollingCondition
+ {
+ /// <summary>
+ /// This method should implement all checks needed to determine if a file
+ /// can be rolled based on the conditions it implies to the file.
+ /// </summary>
+ /// <param name="file">the file to be rolled</param>
+ /// <returns>true when the file has met all conditions to be rolled</returns>
+ bool IsMet(string file);
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/829b2eb5/src/Appender/Rolling/IRollingStrategy.cs
----------------------------------------------------------------------
diff --git a/src/Appender/Rolling/IRollingStrategy.cs b/src/Appender/Rolling/IRollingStrategy.cs
new file mode 100644
index 0000000..94ad6d2
--- /dev/null
+++ b/src/Appender/Rolling/IRollingStrategy.cs
@@ -0,0 +1,36 @@
+#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;
+
+namespace log4net.Appender.Rolling
+{
+ /// <summary>
+ /// An interface that can implement a strategy to roll a file.
+ /// </summary>
+ /// <author>Dominik Psenner</author>
+ public interface IRollingStrategy
+ {
+ /// <summary>
+ /// This method should implement all the rolling operations.
+ /// </summary>
+ /// <param name="file">the file to be rolled</param>
+ void Roll(string file);
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/829b2eb5/src/Appender/Rolling/IndexRollingStrategy.cs
----------------------------------------------------------------------
diff --git a/src/Appender/Rolling/IndexRollingStrategy.cs b/src/Appender/Rolling/IndexRollingStrategy.cs
new file mode 100644
index 0000000..ad58b40
--- /dev/null
+++ b/src/Appender/Rolling/IndexRollingStrategy.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 System;
+using System.IO;
+
+namespace log4net.Appender.Rolling
+{
+ /// <summary>
+ /// This is a simple rolling strategy implementation that rolls a file by
+ /// appending the index 0. If a file exists that is named exactly as that
+ /// that file will be renamed to index 1 until reaching the maximum index.
+ /// The last file will be removed.
+ /// </summary>
+ /// <author>Dominik Psenner</author>
+ public class IndexRollingStrategy : IRollingStrategy
+ {
+ #region Implementation of IRollingStrategy
+
+ /// <summary>
+ /// This method rolls a file with backup indexes between
+ /// [0..10].
+ /// </summary>
+ /// <param name="file"></param>
+ public void Roll(string file)
+ {
+ DoRoll(file, file, 0, 10);
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private void DoRoll(string baseFilename, string currentFilename, int currentIndex, int maxIndex)
+ {
+ if (currentIndex > maxIndex)
+ {
+ if (File.Exists(currentFilename))
+ {
+ File.Delete(currentFilename);
+ }
+ return;
+ }
+ if (!File.Exists(currentFilename))
+ {
+ return;
+ }
+
+ // determine next filename
+ string nextFilename = string.Format("{0}.{1}", baseFilename, currentIndex);
+
+ // iterate the process until we meet the end
+ DoRoll(baseFilename, nextFilename, currentIndex + 1, maxIndex);
+
+ // rename this file now that there's free room after us
+ File.Move(currentFilename, nextFilename);
+ }
+
+ #endregion
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/829b2eb5/src/Appender/RollingFileAppenderNG.cs
----------------------------------------------------------------------
diff --git a/src/Appender/RollingFileAppenderNG.cs b/src/Appender/RollingFileAppenderNG.cs
new file mode 100644
index 0000000..4b79983
--- /dev/null
+++ b/src/Appender/RollingFileAppenderNG.cs
@@ -0,0 +1,152 @@
+#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.Collections;
+using System.Globalization;
+using System.IO;
+
+using log4net.Util;
+using log4net.Core;
+using log4net.Appender.Rolling;
+
+namespace log4net.Appender
+{
+ /// <summary>
+ /// Appender that rolls log files based on size or date or both.
+ /// </summary>
+ /// <author>Dominik Psenner</author>
+ public class RollingFileAppenderNG : FileAppender
+ {
+ #region Public Instance Constructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RollingFileAppenderNG" /> class.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Default constructor.
+ /// </para>
+ /// </remarks>
+ public RollingFileAppenderNG()
+ {
+ // for now set up the cron rolling condition and the index rolling strategy by default
+ RollingCondition = new CronRollingCondition("*", "*", "*", "*", "*");
+ RollingStrategy = new IndexRollingStrategy();
+ }
+
+ #endregion Public Instance Constructors
+
+ #region Public Instance Properties
+
+ /// <summary>
+ /// Gets the strategy to decide whether or not a file should be rolled over.
+ /// </summary>
+ public IRollingCondition RollingCondition
+ {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// Gets the strategy to roll a file.
+ /// </summary>
+ public IRollingStrategy RollingStrategy
+ {
+ get;
+ private set;
+ }
+
+ #endregion Public Instance Properties
+
+ #region Override implementation of FileAppender
+
+ /// <summary>
+ /// Sets the quiet writer being used.
+ /// </summary>
+ /// <remarks>
+ /// This method can be overridden by sub classes.
+ /// </remarks>
+ /// <param name="writer">the writer to set</param>
+ override protected void SetQWForFiles(TextWriter writer)
+ {
+ QuietWriter = new CountingQuietTextWriter(writer, ErrorHandler);
+ }
+
+ /// <summary>
+ /// Write out a logging event.
+ /// </summary>
+ /// <param name="loggingEvent">the event to write to file.</param>
+ /// <remarks>
+ /// <para>
+ /// Handles append time behavior for RollingFileAppenderNG.
+ /// </para>
+ /// </remarks>
+ override protected void Append(LoggingEvent loggingEvent)
+ {
+ RollFileTrigger();
+ base.Append(loggingEvent);
+ }
+
+ /// <summary>
+ /// Write out an array of logging events.
+ /// </summary>
+ /// <param name="loggingEvents">the events to write to file.</param>
+ /// <remarks>
+ /// <para>
+ /// Handles append time behavior for RollingFileAppenderNG.
+ /// </para>
+ /// </remarks>
+ override protected void Append(LoggingEvent[] loggingEvents)
+ {
+ RollFileTrigger();
+ base.Append(loggingEvents);
+ }
+
+ /// <summary>
+ /// Performs any required rolling before outputting the next event
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Handles append time behavior for RollingFileAppenderNG. It checks first
+ /// whether the conditions to roll the file are met and if so asks the roll
+ /// file strategy to do the roll operation.
+ /// </para>
+ /// </remarks>
+ protected void RollFileTrigger()
+ {
+ if (RollingCondition == null)
+ {
+ // TODO throw exception
+ }
+ if (RollingStrategy == null)
+ {
+ // TODO throw exception
+ }
+
+ // check if the rolling conditions are met
+ if (RollingCondition.IsMet(File))
+ {
+ // let the strategy do all the required rolling
+ RollingStrategy.Roll(File);
+ }
+ }
+ #endregion
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/829b2eb5/tests/src/Appender/Rolling/CronRollingConditionTest.cs
----------------------------------------------------------------------
diff --git a/tests/src/Appender/Rolling/CronRollingConditionTest.cs b/tests/src/Appender/Rolling/CronRollingConditionTest.cs
new file mode 100644
index 0000000..8a7f28a
--- /dev/null
+++ b/tests/src/Appender/Rolling/CronRollingConditionTest.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using log4net.Appender.Rolling;
+
+namespace log4net.Tests.Appender.Rolling
+{
+ [TestFixture]
+ public class CronRollingConditionTest
+ {
+ [Test]
+ public void IsMetTest()
+ {
+ Tuple<CronRollingCondition, Tuple<DateTime, bool>[]>[] tests = new Tuple<CronRollingCondition, Tuple<DateTime, bool>[]>[]{
+ Tuple.Create(new CronRollingCondition("*", "*", "*", "*", "5"), new Tuple<DateTime, bool>[]{
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 5, 0), true),
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 5, 1), false),
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 6, 0), false),
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 10, 0), false),
+ Tuple.Create(new DateTime(2009, 10, 10, 13, 5, 1), true),
+ Tuple.Create(new DateTime(2009, 10, 10, 14, 5, 1), true),
+ }),
+ Tuple.Create(new CronRollingCondition("*", "*", "*", "*", "*/3"), new Tuple<DateTime, bool>[]{
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 0, 0), true),
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 0, 1), false),
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 0, 59), false),
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 3, 0), true),
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 3, 59), false),
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 4, 1), false),
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 6, 33), true),
+ Tuple.Create(new DateTime(2009, 10, 10, 12, 10, 0), false),
+ }),
+ };
+ foreach (Tuple<CronRollingCondition, Tuple<DateTime, bool>[]> test in tests)
+ {
+ foreach (Tuple<DateTime, bool> testCheck in test.Item2)
+ {
+ Assert.AreEqual(test.Item1.IsMet(testCheck.Item1), testCheck.Item2, string.Format("failed for {0} with condition {1}", testCheck.Item1, test.Item1));
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/829b2eb5/tests/src/Appender/Rolling/IndexRollingStrategyTest.cs
----------------------------------------------------------------------
diff --git a/tests/src/Appender/Rolling/IndexRollingStrategyTest.cs b/tests/src/Appender/Rolling/IndexRollingStrategyTest.cs
new file mode 100644
index 0000000..b66f7fc
--- /dev/null
+++ b/tests/src/Appender/Rolling/IndexRollingStrategyTest.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using log4net.Appender.Rolling;
+using System.IO;
+
+namespace log4net.Tests.Appender.Rolling
+{
+ [TestFixture]
+ public class IndexRollingStrategyTest
+ {
+ [Test]
+ public void RollTest()
+ {
+ IndexRollingStrategy strategy = new IndexRollingStrategy();
+ List<string> tmpFiles = new List<string>();
+ try
+ {
+ // create a dummy temp file
+ string filename = "logfile.log";
+ // add the file
+ tmpFiles.Add(filename);
+ for (int i = 0; i <= 10; i++)
+ {
+ Console.WriteLine("Now at rolling iteration {0}", i);
+ // roll the file once
+ strategy.Roll(filename);
+ // create filename again
+ using (File.Create(filename))
+ {
+ // we don't need the filestream anymore
+ }
+ tmpFiles.Add(filename + "." + i);
+ // test if there are rolled files for [0..i]
+ for (int j = 0; j < i; j++)
+ {
+ if (!File.Exists(filename + "." + j))
+ {
+ // fail
+ Assert.Fail("The file '{0}' was not rolled correctly at iteration i={1}; j={2}", filename, i, j);
+ }
+ }
+ }
+
+ Console.WriteLine("Now at rolling iteration {0}, this should not create another file", 11);
+ // roll the file once
+ strategy.Roll(filename);
+ // test if there are rolled files for [0..i]
+ for (int j = 0; j <= 10; j++)
+ {
+ if (!File.Exists(filename + "." + j))
+ {
+ // fail
+ Assert.Fail("The file '{0}' was not rolled correctly at iteration j={2}", filename, j);
+ }
+ }
+ if (File.Exists(filename + ".11"))
+ {
+ Assert.Fail("The file '{0}' should not have been rolled further iteration 10", filename);
+ }
+
+ }
+ catch (Exception e)
+ {
+ Assert.Fail("Exception: {0}", e);
+ }
+ finally
+ {
+ // cleanup
+ while (tmpFiles.Count > 0)
+ {
+ if (File.Exists(tmpFiles[0]))
+ {
+ File.Delete(tmpFiles[0]);
+ }
+ tmpFiles.RemoveAt(0);
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/829b2eb5/tests/src/log4net.Tests.vs2012.csproj
----------------------------------------------------------------------
diff --git a/tests/src/log4net.Tests.vs2012.csproj b/tests/src/log4net.Tests.vs2012.csproj
index 7629c5a..c0d8aaa 100644
--- a/tests/src/log4net.Tests.vs2012.csproj
+++ b/tests/src/log4net.Tests.vs2012.csproj
@@ -159,6 +159,8 @@
<Compile Include="Appender\RemotingAppenderTest.cs">
<SubType>Code</SubType>
</Compile>
+ <Compile Include="Appender\Rolling\CronRollingConditionTest.cs" />
+ <Compile Include="Appender\Rolling\IndexRollingStrategyTest.cs" />
<Compile Include="Appender\SmtpPickupDirAppenderTest.cs">
<SubType>Code</SubType>
</Compile>