From 54b28910acb13a5f7b86bb488088ffcb64e916f9 Mon Sep 17 00:00:00 2001 From: Pr0metheus2 Date: Wed, 26 Aug 2026 12:07:41 +0200 Subject: [PATCH 01/11] Fix/MultiFile pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed/MultiFile rollover patterns with an index before the extension: - RolloverFilenameBuilder: the parser was dropping literal text after the final placeholder, including .log. - *$J(.).log now correctly expands: app.log → app.1.log → app.2.log. - Updated MultiFile mask dialog legend: - Fixed incorrectly displayed and placeholders in English and German resources. - Added both usage examples: *$J(.) → app.log, app.log.1, app.log.2 *$J(.).log → app.log, app.1.log, app.2.log - Added the examples in English, German, and Chinese. - Enlarged the dialog and syntax-help label so the date-format lines are no longer clipped. - Fixed/Items in menu File/Multifile -> "Enable MultiFile" and "Multi file mask...", were always greyed out. Now they are displayed normally after the .log file is open. - removed the BackColor and ForeColor assignments for both: - multiFileEnabledStripMenuItem - multifileMaskToolStripMenuItem - Added regression coverage: - Filename-builder tests for app.1.log and app.2.log. - Reader-level test that loads app.log, app.1.log, and app.2.log in correct order using *$J(.).log. - Kept the existing *$J(.) coverage for app.log.1 / app.log.2. Verification: - Full test suite: 1064 passed, 0 failed, 7 skipped. - Resource project build: passed with 0 warnings, 0 errors. --- .../Classes/Log/RolloverFilenameBuilder.cs | 3 ++- src/LogExpert.Resources/Resources.de.resx | 10 ++++++--- src/LogExpert.Resources/Resources.resx | 10 ++++++--- src/LogExpert.Resources/Resources.zh-CN.resx | 4 ++++ src/LogExpert.Tests/LogExpert.Tests.csproj | 6 +++++ src/LogExpert.Tests/RollingNameTest.cs | 4 +++- .../LogfileReaderMultiFileFlagTests.cs | 22 +++++++++++++++++-- .../LogTabWindow/LogTabWindow.designer.cs | 8 +++---- .../Dialogs/MultiFileMaskDialog.Designer.cs | 12 +++++----- 9 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs index 3b8f1061..e449884b 100644 --- a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs +++ b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs @@ -238,9 +238,10 @@ private string EscapeNonvarRegions (string formatString) } } + _ = result.Append(Regex.Escape(segment.ToString())); fmt = result.ToString().Replace('\xFFFD', '*'); return fmt; } #endregion -} \ No newline at end of file +} diff --git a/src/LogExpert.Resources/Resources.de.resx b/src/LogExpert.Resources/Resources.de.resx index e0e19567..3852c64c 100644 --- a/src/LogExpert.Resources/Resources.de.resx +++ b/src/LogExpert.Resources/Resources.de.resx @@ -1680,12 +1680,16 @@ Ein ausgewähltes Tool erscheint in der Iconbar. Alle anderen verfügbaren Tools Muster syntax: * = alle Zeichen (wildcard) -$D(&lt;date&gt;) = Datumsmuster +$D(<date>) = Datumsmuster $I = Dateiindexnummer $J = Dateiindexnummer, versteckt wenn 09 -$J(&lt;prefix&gt;) = Wie $J, jedoch wird ein &lt;prefix&gt; hinzugefügt when es nicht 0 ist +$J(<prefix>) = Wie $J, jedoch wird ein <prefix> hinzugefügt when es nicht 0 ist -&lt;date&gt;: +Beispiele: +*$J(.) → app.log, app.log.1, app.log.2 +*$J(.).log → app.log, app.1.log, app.2.log + +<date>: DD = Tag MM = Monat YY[YY] = Jahr diff --git a/src/LogExpert.Resources/Resources.resx b/src/LogExpert.Resources/Resources.resx index a08b755c..70d5e60d 100644 --- a/src/LogExpert.Resources/Resources.resx +++ b/src/LogExpert.Resources/Resources.resx @@ -1743,12 +1743,16 @@ Checked tools will appear in the icon bar. All other tools are available in the Pattern syntax: * = any characters (wildcard) -$D(&lt;date&gt;) = Date pattern +$D(<date>) = Date pattern $I = File index number $J = File index number, hidden when zero -$J(&lt;prefix&gt;) = Like $J, but adding &lt;prefix&gt; when non-zero +$J(<prefix>) = Like $J, but adding <prefix> when non-zero -&lt;date&gt;: +Examples: +*$J(.) → app.log, app.log.1, app.log.2 +*$J(.).log → app.log, app.1.log, app.2.log + +<date>: DD = day MM = month YY[YY] = year diff --git a/src/LogExpert.Resources/Resources.zh-CN.resx b/src/LogExpert.Resources/Resources.zh-CN.resx index f4af56f5..826db482 100644 --- a/src/LogExpert.Resources/Resources.zh-CN.resx +++ b/src/LogExpert.Resources/Resources.zh-CN.resx @@ -1554,6 +1554,10 @@ $I = 文件索引编号 $J = 文件索引编号,为零时隐藏 $J(<前缀>) = 类似 $J,但在非零时添加 <前缀> +示例: +*$J(.) → app.log, app.log.1, app.log.2 +*$J(.).log → app.log, app.1.log, app.2.log + <日期>: DD = 日 MM = 月 diff --git a/src/LogExpert.Tests/LogExpert.Tests.csproj b/src/LogExpert.Tests/LogExpert.Tests.csproj index addb6a7a..2ead6531 100644 --- a/src/LogExpert.Tests/LogExpert.Tests.csproj +++ b/src/LogExpert.Tests/LogExpert.Tests.csproj @@ -112,6 +112,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/src/LogExpert.Tests/RollingNameTest.cs b/src/LogExpert.Tests/RollingNameTest.cs index a85f94b4..8f0a079c 100644 --- a/src/LogExpert.Tests/RollingNameTest.cs +++ b/src/LogExpert.Tests/RollingNameTest.cs @@ -32,6 +32,7 @@ public void TestFilename1(string expectedResult, string formatString) [TestCase("engine.log", "engine1.log","engine$J.log")] [TestCase("engine1.log", "engine2.log","engine$J.log")] [TestCase("engine.log", "engine.log.1","*$J(.)")] + [TestCase("engine.log", "engine.1.log", "*$J(.).log")] [TestCase("engine_2010-06-12.log", "engine_2010-06-12.log.1", "*$D(yyyy-MM-dd).log$J(.)")] public void TestFilenameAnd1(string fileName, string expectedResult, string formatString) { @@ -45,6 +46,7 @@ public void TestFilenameAnd1(string fileName, string expectedResult, string form [Test] [TestCase("engine.log", "engine.log.2","*$J(.)")] [TestCase("engine.log", "engine.log.2","*.log$J(.)")] + [TestCase("engine.log", "engine.2.log", "*$J(.).log")] public void TestFilenameAnd2(string fileName, string expectedResult, string formatString) { RolloverFilenameBuilder fnb = new(formatString); @@ -65,4 +67,4 @@ public void TestFilenameMinus1(string fileName, string expectedResult, string fo var name = fnb.BuildFileName(); Assert.That(name, Is.EqualTo("engine.log")); } -} \ No newline at end of file +} diff --git a/src/LogExpert.Tests/StreamReaderTests/LogfileReaderMultiFileFlagTests.cs b/src/LogExpert.Tests/StreamReaderTests/LogfileReaderMultiFileFlagTests.cs index 5522313d..ab3edd74 100644 --- a/src/LogExpert.Tests/StreamReaderTests/LogfileReaderMultiFileFlagTests.cs +++ b/src/LogExpert.Tests/StreamReaderTests/LogfileReaderMultiFileFlagTests.cs @@ -26,6 +26,8 @@ public void SetUp () File.Copy(Path.Combine(_testDataDirectory, "app.log"), _logFile); File.Copy(Path.Combine(_testDataDirectory, "app.log.1"), _logFile + ".1"); + File.Copy(Path.Combine(_testDataDirectory, "app.1.log"), Path.Combine(_testDirectory, "app.1.log")); + File.Copy(Path.Combine(_testDataDirectory, "app.2.log"), Path.Combine(_testDirectory, "app.2.log")); _ = PluginRegistry.PluginRegistry.Create(_testDirectory, 500); } @@ -68,6 +70,22 @@ public void SingleFileCtor_MultiFileTrue_ExpandsRollover () }); } + [Test] + public void SingleFileCtor_MultiFileTrue_LoadsIndexBeforeExtension () + { + var options = new MultiFileOptions { FormatPattern = "*$J(.).log" }; + using var reader = CreateSingleFileReader(multiFile: true, options); + + reader.ReadFiles(); + + Assert.Multiple(() => + { + Assert.That(reader.IsMultiFile, Is.True); + Assert.That(reader.GetLogFileInfoList().Select(file => Path.GetFileName(file.FullName)), + Is.EqualTo(new[] { "app.2.log", "app.1.log", "app.log" })); + }); + } + [Test] public void MultiFileCtor_AlwaysMultiFile () { @@ -91,7 +109,7 @@ public void MultiFileCtor_AlwaysMultiFile () }); } - private LogfileReader CreateSingleFileReader (bool multiFile) + private LogfileReader CreateSingleFileReader (bool multiFile, MultiFileOptions? options = null) { return new LogfileReader( _logFile, @@ -99,7 +117,7 @@ private LogfileReader CreateSingleFileReader (bool multiFile) multiFile, bufferCount: 40, linesPerBuffer: 50, - new MultiFileOptions(), + options ?? new MultiFileOptions(), ReaderType.System, PluginRegistry.PluginRegistry.Instance, maximumLineLength: 500, diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.designer.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.designer.cs index c7d64109..add47f8c 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.designer.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.designer.cs @@ -269,9 +269,9 @@ private void InitializeComponent () // // multiFileEnabledStripMenuItem // - multiFileEnabledStripMenuItem.BackColor = SystemColors.Control; + // multiFileEnabledStripMenuItem.BackColor = SystemColors.Control; multiFileEnabledStripMenuItem.CheckOnClick = true; - multiFileEnabledStripMenuItem.ForeColor = SystemColors.ControlDarkDark; + // multiFileEnabledStripMenuItem.ForeColor = SystemColors.ControlDarkDark; multiFileEnabledStripMenuItem.Name = "multiFileEnabledStripMenuItem"; multiFileEnabledStripMenuItem.Size = new Size(165, 22); multiFileEnabledStripMenuItem.Text = "Enable MultiFile"; @@ -279,8 +279,8 @@ private void InitializeComponent () // // multifileMaskToolStripMenuItem // - multifileMaskToolStripMenuItem.BackColor = SystemColors.Control; - multifileMaskToolStripMenuItem.ForeColor = SystemColors.ControlDarkDark; + // multifileMaskToolStripMenuItem.BackColor = SystemColors.Control; + // multifileMaskToolStripMenuItem.ForeColor = SystemColors.ControlDarkDark; multifileMaskToolStripMenuItem.Name = "multifileMaskToolStripMenuItem"; multifileMaskToolStripMenuItem.Size = new Size(165, 22); multifileMaskToolStripMenuItem.Text = "File name mask..."; diff --git a/src/LogExpert.UI/Dialogs/MultiFileMaskDialog.Designer.cs b/src/LogExpert.UI/Dialogs/MultiFileMaskDialog.Designer.cs index d57d7e64..18763c3b 100644 --- a/src/LogExpert.UI/Dialogs/MultiFileMaskDialog.Designer.cs +++ b/src/LogExpert.UI/Dialogs/MultiFileMaskDialog.Designer.cs @@ -121,7 +121,7 @@ private void InitializeComponent() // this.syntaxHelpLabel.Location = new System.Drawing.Point(15, 140); this.syntaxHelpLabel.Name = "syntaxHelpLabel"; - this.syntaxHelpLabel.Size = new System.Drawing.Size(402, 194); + this.syntaxHelpLabel.Size = new System.Drawing.Size(402, 254); this.syntaxHelpLabel.TabIndex = 7; this.syntaxHelpLabel.Text = "Syntax Help Label"; // @@ -129,7 +129,7 @@ private void InitializeComponent() // this.buttonOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonOk.DialogResult = System.Windows.Forms.DialogResult.OK; - this.buttonOk.Location = new System.Drawing.Point(261, 347); + this.buttonOk.Location = new System.Drawing.Point(261, 407); this.buttonOk.Name = "buttonOk"; this.buttonOk.Size = new System.Drawing.Size(75, 23); this.buttonOk.TabIndex = 8; @@ -141,7 +141,7 @@ private void InitializeComponent() // this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.buttonCancel.Location = new System.Drawing.Point(342, 347); + this.buttonCancel.Location = new System.Drawing.Point(342, 407); this.buttonCancel.Name = "buttonCancel"; this.buttonCancel.Size = new System.Drawing.Size(75, 23); this.buttonCancel.TabIndex = 9; @@ -152,7 +152,7 @@ private void InitializeComponent() // this.AcceptButton = this.buttonOk; this.CancelButton = this.buttonCancel; - this.ClientSize = new System.Drawing.Size(434, 386); + this.ClientSize = new System.Drawing.Size(434, 446); this.Controls.Add(this.buttonCancel); this.Controls.Add(this.buttonOk); this.Controls.Add(this.syntaxHelpLabel); @@ -162,7 +162,7 @@ private void InitializeComponent() this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MaximizeBox = false; this.MinimizeBox = false; - this.MinimumSize = new System.Drawing.Size(329, 420); + this.MinimumSize = new System.Drawing.Size(329, 480); this.Name = "MultiFileMaskDialog"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "MultiFile settings"; @@ -188,4 +188,4 @@ private void InitializeComponent() private System.Windows.Forms.Label syntaxHelpLabel; private System.Windows.Forms.Button buttonOk; private System.Windows.Forms.Button buttonCancel; - } \ No newline at end of file + } From 3989ae2a5cfc7e7a54ccfaa0da3cbd9c105948dd Mon Sep 17 00:00:00 2001 From: Pr0metheus2 Date: Wed, 26 Aug 2026 13:22:16 +0200 Subject: [PATCH 02/11] test: add multi-file index test data --- src/LogExpert.Tests/TestData/app.1.log | 1 + src/LogExpert.Tests/TestData/app.2.log | 1 + 2 files changed, 2 insertions(+) create mode 100644 src/LogExpert.Tests/TestData/app.1.log create mode 100644 src/LogExpert.Tests/TestData/app.2.log diff --git a/src/LogExpert.Tests/TestData/app.1.log b/src/LogExpert.Tests/TestData/app.1.log new file mode 100644 index 00000000..dc4e726a --- /dev/null +++ b/src/LogExpert.Tests/TestData/app.1.log @@ -0,0 +1 @@ +app.1.log \ No newline at end of file diff --git a/src/LogExpert.Tests/TestData/app.2.log b/src/LogExpert.Tests/TestData/app.2.log new file mode 100644 index 00000000..67dfe9df --- /dev/null +++ b/src/LogExpert.Tests/TestData/app.2.log @@ -0,0 +1 @@ +app.2.log \ No newline at end of file From 15c3d960eb1dd8f3e11729998a72f5da9aa2b81e Mon Sep 17 00:00:00 2001 From: Pr0metheus Date: Sat, 29 Aug 2026 11:36:47 +0200 Subject: [PATCH 03/11] Fixed from when to wenn --- src/LogExpert.Resources/Resources.de.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LogExpert.Resources/Resources.de.resx b/src/LogExpert.Resources/Resources.de.resx index 3852c64c..ac74e3ad 100644 --- a/src/LogExpert.Resources/Resources.de.resx +++ b/src/LogExpert.Resources/Resources.de.resx @@ -1683,7 +1683,7 @@ Ein ausgewähltes Tool erscheint in der Iconbar. Alle anderen verfügbaren Tools $D(<date>) = Datumsmuster $I = Dateiindexnummer $J = Dateiindexnummer, versteckt wenn 09 -$J(<prefix>) = Wie $J, jedoch wird ein <prefix> hinzugefügt when es nicht 0 ist +$J(<prefix>) = Wie $J, jedoch wird ein <prefix> hinzugefügt wenn es nicht 0 ist Beispiele: *$J(.) → app.log, app.log.1, app.log.2 From 905c979e1a023e58d364109bc2f7843a78b0d9f5 Mon Sep 17 00:00:00 2001 From: Pr0metheus Date: Sat, 29 Aug 2026 11:37:14 +0200 Subject: [PATCH 04/11] Removed old commented lines --- .../Dialogs/LogTabWindow/LogTabWindow.designer.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.designer.cs b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.designer.cs index add47f8c..9da5eea6 100644 --- a/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.designer.cs +++ b/src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.designer.cs @@ -269,9 +269,7 @@ private void InitializeComponent () // // multiFileEnabledStripMenuItem // - // multiFileEnabledStripMenuItem.BackColor = SystemColors.Control; multiFileEnabledStripMenuItem.CheckOnClick = true; - // multiFileEnabledStripMenuItem.ForeColor = SystemColors.ControlDarkDark; multiFileEnabledStripMenuItem.Name = "multiFileEnabledStripMenuItem"; multiFileEnabledStripMenuItem.Size = new Size(165, 22); multiFileEnabledStripMenuItem.Text = "Enable MultiFile"; @@ -279,8 +277,6 @@ private void InitializeComponent () // // multifileMaskToolStripMenuItem // - // multifileMaskToolStripMenuItem.BackColor = SystemColors.Control; - // multifileMaskToolStripMenuItem.ForeColor = SystemColors.ControlDarkDark; multifileMaskToolStripMenuItem.Name = "multifileMaskToolStripMenuItem"; multifileMaskToolStripMenuItem.Size = new Size(165, 22); multifileMaskToolStripMenuItem.Text = "File name mask..."; From 1fcb26251a698cedcdcdb562bd213488886dc59a Mon Sep 17 00:00:00 2001 From: Pr0metheus Date: Sat, 29 Aug 2026 12:01:31 +0200 Subject: [PATCH 05/11] Update RollingNameTest.cs Fixed by locating and parsing $D(...) in the escaped format string. Offsets remain correct when literal regex metacharacters appear before the date placeholder. Added a regression test for app.$D(yyyy-MM-dd).log that verifies date parsing and rebuilding. Added cases which cover: - $I with a trailing literal .log, starting from a rotated file. - $D plus $J(.) followed by a trailing .log, also starting from a rotated file. --- src/LogExpert.Tests/RollingNameTest.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/LogExpert.Tests/RollingNameTest.cs b/src/LogExpert.Tests/RollingNameTest.cs index 8f0a079c..3f9984a4 100644 --- a/src/LogExpert.Tests/RollingNameTest.cs +++ b/src/LogExpert.Tests/RollingNameTest.cs @@ -33,6 +33,10 @@ public void TestFilename1(string expectedResult, string formatString) [TestCase("engine1.log", "engine2.log","engine$J.log")] [TestCase("engine.log", "engine.log.1","*$J(.)")] [TestCase("engine.log", "engine.1.log", "*$J(.).log")] + [TestCase("engine.log.1", "engine.log.2", "*$J(.)")] + [TestCase("engine.1.log", "engine.2.log", "*$J(.).log")] + [TestCase("engine1.log", "engine2.log", "*$I.log")] + [TestCase("engine_2010-06-12.1.log", "engine_2010-06-12.2.log", "*$D(yyyy-MM-dd)$J(.).log")] [TestCase("engine_2010-06-12.log", "engine_2010-06-12.log.1", "*$D(yyyy-MM-dd).log$J(.)")] public void TestFilenameAnd1(string fileName, string expectedResult, string formatString) { @@ -56,6 +60,16 @@ public void TestFilenameAnd2(string fileName, string expectedResult, string form Assert.That(name, Is.EqualTo(expectedResult)); } + [Test] + public void BuildFileName_DatePatternAfterRegexMetacharacter_IncrementsDate () + { + RolloverFilenameBuilder fnb = new("app.$D(yyyy-MM-dd).log"); + fnb.SetFileName("app.2010-06-12.log"); + + fnb.IncrementDate(); + + Assert.That(fnb.BuildFileName(), Is.EqualTo("app.2010-06-13.log")); + } [Test] [TestCase("engine1.log", "engine.log","engine$J.log")] From 568bb043e5a42958450984067f3cfa4fde3152fa Mon Sep 17 00:00:00 2001 From: Pr0metheus Date: Sat, 29 Aug 2026 12:17:11 +0200 Subject: [PATCH 06/11] Update RolloverFilenameBuilder.cs - Added FlushEscaped() to share duplicated escaping code. - Fixed parsing of $J() from rotated files, so both: - app.log.1 - app.1.log correctly identify index 1. - Made wildcard matching non-greedy and anchored the generated regex to the complete filename. - Updated rebuilding logic to remove an existing prefix plus index together before inserting the new index. - Fixed $D(...) parsing to use positions in the escaped format string, preventing errors when a literal regex character such as . appears before $D. --- .../Classes/Log/RolloverFilenameBuilder.cs | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs index e449884b..2d7b1476 100644 --- a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs +++ b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs @@ -116,15 +116,23 @@ public string BuildFileName () if (_indexGroup != null && _indexGroup.Success) { - fileName = fileName.Remove(_indexGroup.Index, _indexGroup.Length); + var indexPosition = _indexGroup.Index; + var indexLength = _indexGroup.Length; + if (_condGroup != null && _condGroup.Success) + { + indexPosition = _condGroup.Index; + indexLength += _condGroup.Length; + } + + fileName = fileName.Remove(indexPosition, indexLength); if (!_hideZeroIndex || Index > 0) { var format = "D" + _indexGroup.Length; - fileName = fileName.Insert(_indexGroup.Index, Index.ToString(format)); + fileName = fileName.Insert(indexPosition, Index.ToString(format)); if (_hideZeroIndex && _condContent != null) { - fileName = fileName.Insert(_indexGroup.Index, _condContent); + fileName = fileName.Insert(indexPosition, _condContent); } } } @@ -141,14 +149,14 @@ public string BuildFileName () private void ParseFormatString (string formatString) { var fmt = EscapeNonvarRegions(formatString); - var datePos = formatString.IndexOf("$D(", StringComparison.Ordinal); + var datePos = fmt.IndexOf("$D(", StringComparison.Ordinal); if (datePos != -1) { - var endPos = formatString.IndexOf(')', datePos); + var endPos = fmt.IndexOf(')', datePos); if (endPos != -1) { - _dateTimeFormat = formatString.Substring(datePos + 3, endPos - datePos - 3) + _dateTimeFormat = fmt.Substring(datePos + 3, endPos - datePos - 3) .ToUpperInvariant() .Replace('D', 'd') .Replace('Y', 'y'); @@ -176,12 +184,15 @@ private void ParseFormatString (string formatString) } } - fmt = fmt.Replace("*", ".*", StringComparison.Ordinal); + fmt = fmt.Replace("*", ".*?", StringComparison.Ordinal); _hideZeroIndex = fmt.Contains("$J", StringComparison.Ordinal); fmt = fmt.Replace("$I", "(?'index'[\\d]+)", StringComparison.Ordinal); - fmt = fmt.Replace("$J", "(?'index'[\\d]*)", StringComparison.Ordinal); + var optionalIndexPattern = _condContent != null + ? $"(?:(?'cond'{Regex.Escape(_condContent)})(?'index'[\\d]+)|(?'index'))" + : "(?'index'[\\d]*)"; + fmt = fmt.Replace("$J", optionalIndexPattern, StringComparison.Ordinal); - _regex = new Regex(fmt); + _regex = new Regex(@"\A" + fmt + @"\z"); } private string EscapeNonvarRegions (string formatString) @@ -192,6 +203,12 @@ private string EscapeNonvarRegions (string formatString) StringBuilder result = new(); StringBuilder segment = new(); + void FlushEscaped () + { + _ = result.Append(Regex.Escape(segment.ToString())); + segment = new StringBuilder(); + } + for (var i = 0; i < fmt.Length; ++i) { switch (state) @@ -199,8 +216,7 @@ private string EscapeNonvarRegions (string formatString) case 0: // looking for $ if (fmt[i] == '$') { - _ = result.Append(Regex.Escape(segment.ToString())); - segment = new StringBuilder(); + FlushEscaped(); state = 1; } @@ -238,7 +254,7 @@ private string EscapeNonvarRegions (string formatString) } } - _ = result.Append(Regex.Escape(segment.ToString())); + FlushEscaped(); fmt = result.ToString().Replace('\xFFFD', '*'); return fmt; } From ae20df68fa750a433a1ec538aabe1f251a8680f7 Mon Sep 17 00:00:00 2001 From: Pr0metheus2 Date: Tue, 1 Sep 2026 15:35:04 +0200 Subject: [PATCH 07/11] Update Resources.de.resx --- src/LogExpert.Resources/Resources.de.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LogExpert.Resources/Resources.de.resx b/src/LogExpert.Resources/Resources.de.resx index 789622b4..973bb2f2 100644 --- a/src/LogExpert.Resources/Resources.de.resx +++ b/src/LogExpert.Resources/Resources.de.resx @@ -1682,7 +1682,7 @@ Ein ausgewähltes Tool erscheint in der Iconbar. Alle anderen verfügbaren Tools * = alle Zeichen (wildcard) $D(<date>) = Datumsmuster $I = Dateiindexnummer -$J = Dateiindexnummer, versteckt wenn 09 +$J = Dateiindexnummer, versteckt wenn null $J(<prefix>) = Wie $J, jedoch wird ein <prefix> hinzugefügt wenn es nicht 0 ist Beispiele: From 00d4c26f34c0746ddec631fd078f72b20b27627b Mon Sep 17 00:00:00 2001 From: Pr0metheus2 Date: Tue, 1 Sep 2026 15:53:31 +0200 Subject: [PATCH 08/11] Update LogfileReaderMultiFileFlagTests.cs --- .../StreamReaderTests/LogfileReaderMultiFileFlagTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LogExpert.Tests/StreamReaderTests/LogfileReaderMultiFileFlagTests.cs b/src/LogExpert.Tests/StreamReaderTests/LogfileReaderMultiFileFlagTests.cs index ab3edd74..df03440e 100644 --- a/src/LogExpert.Tests/StreamReaderTests/LogfileReaderMultiFileFlagTests.cs +++ b/src/LogExpert.Tests/StreamReaderTests/LogfileReaderMultiFileFlagTests.cs @@ -26,8 +26,6 @@ public void SetUp () File.Copy(Path.Combine(_testDataDirectory, "app.log"), _logFile); File.Copy(Path.Combine(_testDataDirectory, "app.log.1"), _logFile + ".1"); - File.Copy(Path.Combine(_testDataDirectory, "app.1.log"), Path.Combine(_testDirectory, "app.1.log")); - File.Copy(Path.Combine(_testDataDirectory, "app.2.log"), Path.Combine(_testDirectory, "app.2.log")); _ = PluginRegistry.PluginRegistry.Create(_testDirectory, 500); } @@ -74,6 +72,8 @@ public void SingleFileCtor_MultiFileTrue_ExpandsRollover () public void SingleFileCtor_MultiFileTrue_LoadsIndexBeforeExtension () { var options = new MultiFileOptions { FormatPattern = "*$J(.).log" }; + File.Copy(Path.Combine(_testDataDirectory, "app.1.log"), Path.Combine(_testDirectory, "app.1.log")); + File.Copy(Path.Combine(_testDataDirectory, "app.2.log"), Path.Combine(_testDirectory, "app.2.log")); using var reader = CreateSingleFileReader(multiFile: true, options); reader.ReadFiles(); From d23d2282f9e65e13b431ad66485dd466a57a6c82 Mon Sep 17 00:00:00 2001 From: Pr0metheus2 Date: Thu, 3 Sep 2026 09:03:19 +0200 Subject: [PATCH 09/11] Update --- .../Classes/Log/RolloverFilenameBuilder.cs | 63 +++++++++---------- src/LogExpert.Tests/RollingNameTest.cs | 15 ++++- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs index 2d7b1476..ce8ab195 100644 --- a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs +++ b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs @@ -28,7 +28,6 @@ public class RolloverFilenameBuilder #region Fields private string _condContent; - private Group _condGroup; private string _currentFileName; private Group _dateGroup; @@ -41,6 +40,7 @@ public class RolloverFilenameBuilder private bool _hideZeroIndex; private Group _indexGroup; + private Group _indexPartGroup; private Regex _regex; #endregion @@ -89,7 +89,7 @@ public void SetFileName (string fileName) Index = _indexGroup.Value.Length > 0 ? int.Parse(_indexGroup.Value) : 0; } - _condGroup = match.Groups["cond"]; + _indexPartGroup = match.Groups["indexPart"]; } } @@ -116,23 +116,15 @@ public string BuildFileName () if (_indexGroup != null && _indexGroup.Success) { - var indexPosition = _indexGroup.Index; - var indexLength = _indexGroup.Length; - if (_condGroup != null && _condGroup.Success) - { - indexPosition = _condGroup.Index; - indexLength += _condGroup.Length; - } + fileName = fileName.Remove(_indexPartGroup.Index, _indexPartGroup.Length); - fileName = fileName.Remove(indexPosition, indexLength); - - if (!_hideZeroIndex || Index > 0) + if (Index > 0 || (!_hideZeroIndex && _indexGroup.Length > 0)) { var format = "D" + _indexGroup.Length; - fileName = fileName.Insert(indexPosition, Index.ToString(format)); + fileName = fileName.Insert(_indexPartGroup.Index, Index.ToString(format)); if (_hideZeroIndex && _condContent != null) { - fileName = fileName.Insert(indexPosition, _condContent); + fileName = fileName.Insert(_indexPartGroup.Index, _condContent); } } } @@ -186,13 +178,14 @@ private void ParseFormatString (string formatString) fmt = fmt.Replace("*", ".*?", StringComparison.Ordinal); _hideZeroIndex = fmt.Contains("$J", StringComparison.Ordinal); - fmt = fmt.Replace("$I", "(?'index'[\\d]+)", StringComparison.Ordinal); - var optionalIndexPattern = _condContent != null - ? $"(?:(?'cond'{Regex.Escape(_condContent)})(?'index'[\\d]+)|(?'index'))" - : "(?'index'[\\d]*)"; - fmt = fmt.Replace("$J", optionalIndexPattern, StringComparison.Ordinal); - - _regex = new Regex(@"\A" + fmt + @"\z"); + const string indexPattern = "(?'indexPart'(?'index'[\\d]*))"; + var conditionalIndexPattern = _condContent != null + ? $"(?'indexPart'(?:{Regex.Escape(_condContent)}(?'index'[\\d]+)|(?'index')))" + : indexPattern; + fmt = fmt.Replace("$I", indexPattern, StringComparison.Ordinal); + fmt = fmt.Replace("$J", conditionalIndexPattern, StringComparison.Ordinal); + + _regex = new Regex(fmt + @"\z"); } private string EscapeNonvarRegions (string formatString) @@ -203,12 +196,6 @@ private string EscapeNonvarRegions (string formatString) StringBuilder result = new(); StringBuilder segment = new(); - void FlushEscaped () - { - _ = result.Append(Regex.Escape(segment.ToString())); - segment = new StringBuilder(); - } - for (var i = 0; i < fmt.Length; ++i) { switch (state) @@ -216,7 +203,7 @@ void FlushEscaped () case 0: // looking for $ if (fmt[i] == '$') { - FlushEscaped(); + AppendEscapedSegment(result, segment); state = 1; } @@ -224,8 +211,7 @@ void FlushEscaped () break; case 1: // the char behind $ _ = segment.Append(fmt[i]); - _ = result.Append(segment); - segment = new StringBuilder(); + AppendSegment(result, segment); state = 2; break; case 2: // checking if ( or other char @@ -245,8 +231,7 @@ void FlushEscaped () _ = segment.Append(fmt[i]); if (fmt[i] == ')') { - _ = result.Append(segment); - segment = new StringBuilder(); + AppendSegment(result, segment); state = 0; } @@ -254,10 +239,22 @@ void FlushEscaped () } } - FlushEscaped(); + AppendEscapedSegment(result, segment); fmt = result.ToString().Replace('\xFFFD', '*'); return fmt; } + private static void AppendEscapedSegment (StringBuilder result, StringBuilder segment) + { + _ = result.Append(Regex.Escape(segment.ToString())); + _ = segment.Clear(); + } + + private static void AppendSegment (StringBuilder result, StringBuilder segment) + { + _ = result.Append(segment); + _ = segment.Clear(); + } + #endregion } diff --git a/src/LogExpert.Tests/RollingNameTest.cs b/src/LogExpert.Tests/RollingNameTest.cs index 3f9984a4..9b39ff50 100644 --- a/src/LogExpert.Tests/RollingNameTest.cs +++ b/src/LogExpert.Tests/RollingNameTest.cs @@ -35,7 +35,7 @@ public void TestFilename1(string expectedResult, string formatString) [TestCase("engine.log", "engine.1.log", "*$J(.).log")] [TestCase("engine.log.1", "engine.log.2", "*$J(.)")] [TestCase("engine.1.log", "engine.2.log", "*$J(.).log")] - [TestCase("engine1.log", "engine2.log", "*$I.log")] + [TestCase("app.log", "app1.log", "*$I.log")] [TestCase("engine_2010-06-12.1.log", "engine_2010-06-12.2.log", "*$D(yyyy-MM-dd)$J(.).log")] [TestCase("engine_2010-06-12.log", "engine_2010-06-12.log.1", "*$D(yyyy-MM-dd).log$J(.)")] public void TestFilenameAnd1(string fileName, string expectedResult, string formatString) @@ -61,7 +61,7 @@ public void TestFilenameAnd2(string fileName, string expectedResult, string form } [Test] - public void BuildFileName_DatePatternAfterRegexMetacharacter_IncrementsDate () + public void TestFilenameDateAfterRegexMetacharacter () { RolloverFilenameBuilder fnb = new("app.$D(yyyy-MM-dd).log"); fnb.SetFileName("app.2010-06-12.log"); @@ -71,6 +71,17 @@ public void BuildFileName_DatePatternAfterRegexMetacharacter_IncrementsDate () Assert.That(fnb.BuildFileName(), Is.EqualTo("app.2010-06-13.log")); } + [Test] + public void BuildFileName_FullPathWithNonWildcardMask_IncrementsIndex () + { + RolloverFilenameBuilder fnb = new("engine$J.log"); + fnb.SetFileName(@"C:\logs\engine1.log"); + + fnb.Index += 1; + + Assert.That(fnb.BuildFileName(), Is.EqualTo(@"C:\logs\engine2.log")); + } + [Test] [TestCase("engine1.log", "engine.log","engine$J.log")] public void TestFilenameMinus1(string fileName, string expectedResult, string formatString) From 99d14e8a28083058b288bb5e18ba17f1e4ea8512 Mon Sep 17 00:00:00 2001 From: Pr0metheus2 Date: Thu, 3 Sep 2026 09:59:21 +0200 Subject: [PATCH 10/11] Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added a settings migration for the corrected MultiFile mask behavior. Older LogExpert versions accidentally ignored the trailing .log in saved *$J(.).log masks, so users effectively got app.log.1 style rollover files. The parser now correctly supports app.1.log for that mask, but this would otherwise change existing users’ saved behavior. To preserve compatibility, settings version 2 migrates existing saved *$J(.).log preferences to *$J(.). New version-2 settings keep both patterns distinct: - *$J(.) for app.log.1 - *$J(.).log for app.1.log Added tests for migrating old settings and for ensuring new settings are not changed. --- .../LegacyPreferencesMigrator.cs | 19 ++++++++++++++- .../LegacyPreferencesMigratorTests.cs | 23 +++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/LogExpert.Configuration/LegacyPreferencesMigrator.cs b/src/LogExpert.Configuration/LegacyPreferencesMigrator.cs index cb31a16d..fc2d211e 100644 --- a/src/LogExpert.Configuration/LegacyPreferencesMigrator.cs +++ b/src/LogExpert.Configuration/LegacyPreferencesMigrator.cs @@ -10,7 +10,7 @@ namespace LogExpert.Configuration; public static class LegacyPreferencesMigrator { /// Current schema version. Bumped whenever a new migration step is added. - public const int CURRENT_SETTINGS_VERSION = 1; + public const int CURRENT_SETTINGS_VERSION = 2; /// /// Migrates the given in place. Returns if any @@ -29,6 +29,13 @@ public static bool Migrate (Settings settings) changed = true; } + if (settings.SettingsVersion < 2) + { + MigrateToV2(settings); + settings.SettingsVersion = 2; + changed = true; + } + return changed; } @@ -55,4 +62,14 @@ private static void MigrateToV1 (Settings settings) } #pragma warning restore CS0618 } + + private static void MigrateToV2 (Settings settings) + { + // Before the parser fix, the trailing .log in this pattern was ignored, making it behave + // like *$J(.). Preserve that behavior for existing saved preferences. + if (settings.Preferences?.MultiFileOptions?.FormatPattern == "*$J(.).log") + { + settings.Preferences.MultiFileOptions.FormatPattern = "*$J(.)"; + } + } } diff --git a/src/LogExpert.Tests/ConfigManagerTests/LegacyPreferencesMigratorTests.cs b/src/LogExpert.Tests/ConfigManagerTests/LegacyPreferencesMigratorTests.cs index 80f5c7f0..10ec9d42 100644 --- a/src/LogExpert.Tests/ConfigManagerTests/LegacyPreferencesMigratorTests.cs +++ b/src/LogExpert.Tests/ConfigManagerTests/LegacyPreferencesMigratorTests.cs @@ -1,5 +1,6 @@ using LogExpert.Configuration; using LogExpert.Core.Config; +using LogExpert.Core.Entities; using NUnit.Framework; @@ -23,7 +24,7 @@ public void V0Settings_WithMaskPrioTrue_BecomesMaskThenHistory () Assert.That(changed, Is.True); Assert.That(settings.Preferences.ColumnizerSelectionPriority, Is.EqualTo(ColumnizerSelectionPriority.MaskThenHistory)); - Assert.That(settings.SettingsVersion, Is.EqualTo(1)); + Assert.That(settings.SettingsVersion, Is.EqualTo(2)); } [Test] @@ -34,7 +35,7 @@ public void V0Settings_WithMaskPrioFalse_KeepsDefaultPriority () _ = LegacyPreferencesMigrator.Migrate(settings); Assert.That(settings.Preferences.ColumnizerSelectionPriority, Is.EqualTo(ColumnizerSelectionPriority.HistoryThenMask)); - Assert.That(settings.SettingsVersion, Is.EqualTo(1)); + Assert.That(settings.SettingsVersion, Is.EqualTo(2)); } [Test] @@ -53,10 +54,27 @@ public void V0Settings_PreExistingMaskEntries_AreRewrittenToRegex () Assert.That(settings.Preferences.ColumnizerMaskList[0].Type, Is.EqualTo(MaskType.Regex)); } + [Test] + public void V1Settings_WithLegacyMultiFilePattern_PreservesPreviousBehavior () + { + var settings = new Settings { SettingsVersion = 1 }; + settings.Preferences.MultiFileOptions = new MultiFileOptions { FormatPattern = "*$J(.).log" }; + + var changed = LegacyPreferencesMigrator.Migrate(settings); + + Assert.Multiple(() => + { + Assert.That(changed, Is.True); + Assert.That(settings.SettingsVersion, Is.EqualTo(2)); + Assert.That(settings.Preferences.MultiFileOptions.FormatPattern, Is.EqualTo("*$J(.)")); + }); + } + [Test] public void CurrentSettings_IsNoOp () { var settings = new Settings { SettingsVersion = LegacyPreferencesMigrator.CURRENT_SETTINGS_VERSION }; + settings.Preferences.MultiFileOptions = new MultiFileOptions { FormatPattern = "*$J(.).log" }; settings.Preferences.ColumnizerMaskList.Add(new ColumnizerMaskEntry { Mask = "*.log", @@ -68,6 +86,7 @@ public void CurrentSettings_IsNoOp () Assert.That(changed, Is.False); Assert.That(settings.Preferences.ColumnizerMaskList[0].Type, Is.EqualTo(MaskType.Glob)); + Assert.That(settings.Preferences.MultiFileOptions.FormatPattern, Is.EqualTo("*$J(.).log")); } [Test] From a1320e77abb9fb7e89eabd4b4fcf418cb0b1b359 Mon Sep 17 00:00:00 2001 From: Pr0metheus2 Date: Tue, 8 Sep 2026 10:14:58 +0200 Subject: [PATCH 11/11] Change update --- .../LegacyPreferencesMigrator.cs | 18 +-------------- .../Classes/Log/RolloverFilenameBuilder.cs | 7 +++--- .../LegacyPreferencesMigratorTests.cs | 23 ++----------------- src/LogExpert.Tests/RollingNameTest.cs | 2 +- 4 files changed, 8 insertions(+), 42 deletions(-) diff --git a/src/LogExpert.Configuration/LegacyPreferencesMigrator.cs b/src/LogExpert.Configuration/LegacyPreferencesMigrator.cs index fc2d211e..a7c08677 100644 --- a/src/LogExpert.Configuration/LegacyPreferencesMigrator.cs +++ b/src/LogExpert.Configuration/LegacyPreferencesMigrator.cs @@ -10,7 +10,7 @@ namespace LogExpert.Configuration; public static class LegacyPreferencesMigrator { /// Current schema version. Bumped whenever a new migration step is added. - public const int CURRENT_SETTINGS_VERSION = 2; + public const int CURRENT_SETTINGS_VERSION = 1; /// /// Migrates the given in place. Returns if any @@ -29,13 +29,6 @@ public static bool Migrate (Settings settings) changed = true; } - if (settings.SettingsVersion < 2) - { - MigrateToV2(settings); - settings.SettingsVersion = 2; - changed = true; - } - return changed; } @@ -63,13 +56,4 @@ private static void MigrateToV1 (Settings settings) #pragma warning restore CS0618 } - private static void MigrateToV2 (Settings settings) - { - // Before the parser fix, the trailing .log in this pattern was ignored, making it behave - // like *$J(.). Preserve that behavior for existing saved preferences. - if (settings.Preferences?.MultiFileOptions?.FormatPattern == "*$J(.).log") - { - settings.Preferences.MultiFileOptions.FormatPattern = "*$J(.)"; - } - } } diff --git a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs index ce8ab195..dd1c2087 100644 --- a/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs +++ b/src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs @@ -118,7 +118,7 @@ public string BuildFileName () { fileName = fileName.Remove(_indexPartGroup.Index, _indexPartGroup.Length); - if (Index > 0 || (!_hideZeroIndex && _indexGroup.Length > 0)) + if (!_hideZeroIndex || Index > 0) { var format = "D" + _indexGroup.Length; fileName = fileName.Insert(_indexPartGroup.Index, Index.ToString(format)); @@ -178,10 +178,11 @@ private void ParseFormatString (string formatString) fmt = fmt.Replace("*", ".*?", StringComparison.Ordinal); _hideZeroIndex = fmt.Contains("$J", StringComparison.Ordinal); - const string indexPattern = "(?'indexPart'(?'index'[\\d]*))"; + const string indexPattern = "(?'indexPart'(?'index'[\\d]+))"; + const string hiddenZeroIndexPattern = "(?'indexPart'(?'index'[\\d]*))"; var conditionalIndexPattern = _condContent != null ? $"(?'indexPart'(?:{Regex.Escape(_condContent)}(?'index'[\\d]+)|(?'index')))" - : indexPattern; + : hiddenZeroIndexPattern; fmt = fmt.Replace("$I", indexPattern, StringComparison.Ordinal); fmt = fmt.Replace("$J", conditionalIndexPattern, StringComparison.Ordinal); diff --git a/src/LogExpert.Tests/ConfigManagerTests/LegacyPreferencesMigratorTests.cs b/src/LogExpert.Tests/ConfigManagerTests/LegacyPreferencesMigratorTests.cs index 10ec9d42..80f5c7f0 100644 --- a/src/LogExpert.Tests/ConfigManagerTests/LegacyPreferencesMigratorTests.cs +++ b/src/LogExpert.Tests/ConfigManagerTests/LegacyPreferencesMigratorTests.cs @@ -1,6 +1,5 @@ using LogExpert.Configuration; using LogExpert.Core.Config; -using LogExpert.Core.Entities; using NUnit.Framework; @@ -24,7 +23,7 @@ public void V0Settings_WithMaskPrioTrue_BecomesMaskThenHistory () Assert.That(changed, Is.True); Assert.That(settings.Preferences.ColumnizerSelectionPriority, Is.EqualTo(ColumnizerSelectionPriority.MaskThenHistory)); - Assert.That(settings.SettingsVersion, Is.EqualTo(2)); + Assert.That(settings.SettingsVersion, Is.EqualTo(1)); } [Test] @@ -35,7 +34,7 @@ public void V0Settings_WithMaskPrioFalse_KeepsDefaultPriority () _ = LegacyPreferencesMigrator.Migrate(settings); Assert.That(settings.Preferences.ColumnizerSelectionPriority, Is.EqualTo(ColumnizerSelectionPriority.HistoryThenMask)); - Assert.That(settings.SettingsVersion, Is.EqualTo(2)); + Assert.That(settings.SettingsVersion, Is.EqualTo(1)); } [Test] @@ -54,27 +53,10 @@ public void V0Settings_PreExistingMaskEntries_AreRewrittenToRegex () Assert.That(settings.Preferences.ColumnizerMaskList[0].Type, Is.EqualTo(MaskType.Regex)); } - [Test] - public void V1Settings_WithLegacyMultiFilePattern_PreservesPreviousBehavior () - { - var settings = new Settings { SettingsVersion = 1 }; - settings.Preferences.MultiFileOptions = new MultiFileOptions { FormatPattern = "*$J(.).log" }; - - var changed = LegacyPreferencesMigrator.Migrate(settings); - - Assert.Multiple(() => - { - Assert.That(changed, Is.True); - Assert.That(settings.SettingsVersion, Is.EqualTo(2)); - Assert.That(settings.Preferences.MultiFileOptions.FormatPattern, Is.EqualTo("*$J(.)")); - }); - } - [Test] public void CurrentSettings_IsNoOp () { var settings = new Settings { SettingsVersion = LegacyPreferencesMigrator.CURRENT_SETTINGS_VERSION }; - settings.Preferences.MultiFileOptions = new MultiFileOptions { FormatPattern = "*$J(.).log" }; settings.Preferences.ColumnizerMaskList.Add(new ColumnizerMaskEntry { Mask = "*.log", @@ -86,7 +68,6 @@ public void CurrentSettings_IsNoOp () Assert.That(changed, Is.False); Assert.That(settings.Preferences.ColumnizerMaskList[0].Type, Is.EqualTo(MaskType.Glob)); - Assert.That(settings.Preferences.MultiFileOptions.FormatPattern, Is.EqualTo("*$J(.).log")); } [Test] diff --git a/src/LogExpert.Tests/RollingNameTest.cs b/src/LogExpert.Tests/RollingNameTest.cs index 9b39ff50..f198f7a7 100644 --- a/src/LogExpert.Tests/RollingNameTest.cs +++ b/src/LogExpert.Tests/RollingNameTest.cs @@ -35,7 +35,7 @@ public void TestFilename1(string expectedResult, string formatString) [TestCase("engine.log", "engine.1.log", "*$J(.).log")] [TestCase("engine.log.1", "engine.log.2", "*$J(.)")] [TestCase("engine.1.log", "engine.2.log", "*$J(.).log")] - [TestCase("app.log", "app1.log", "*$I.log")] + [TestCase("engine1.log", "engine2.log", "*$I.log")] [TestCase("engine_2010-06-12.1.log", "engine_2010-06-12.2.log", "*$D(yyyy-MM-dd)$J(.).log")] [TestCase("engine_2010-06-12.log", "engine_2010-06-12.log.1", "*$D(yyyy-MM-dd).log$J(.)")] public void TestFilenameAnd1(string fileName, string expectedResult, string formatString)