public void TestAppendTwoSourcesWrongOrderSeparateChangesPartialInvalidation() { var source1 = new InMemoryLogFile(); source1.AddEntry("A", LevelFlags.None, new DateTime(2019, 5, 28, 00, 34, 0)); source1.AddEntry("C", LevelFlags.None, new DateTime(2019, 5, 28, 00, 36, 0)); var source2 = new InMemoryLogFile(); source2.AddEntry("B", LevelFlags.None, new DateTime(2019, 5, 28, 00, 35, 0)); source2.AddEntry("D", LevelFlags.None, new DateTime(2019, 5, 28, 00, 37, 0)); var index = new MergedLogFileIndex(source1, source2); var changes = index.Process(new MergedLogFilePendingModification(source1, new LogFileSection(0, 2))); changes.Should().Equal(new object[] { new LogFileSection(0, 2) }); changes = index.Process(new MergedLogFilePendingModification(source2, new LogFileSection(0, 2))); changes.Should().Equal(new object[] { LogFileSection.Invalidate(1, 1), new LogFileSection(1, 3) }); }
public void TestOneLine2() { var logFile = new MultiLineLogFile(_taskScheduler, _source.Object, TimeSpan.Zero); logFile.AddListener(_listener.Object, TimeSpan.Zero, 10); _lines.Add(new LogLine(0, 0, "INFO: Hello ", LevelFlags.Info)); logFile.OnLogFileModified(_source.Object, new LogFileSection(0, 1)); _taskScheduler.RunOnce(); logFile.Count.Should().Be(1); _changes.Should().Equal(new object[] { LogFileSection.Reset, new LogFileSection(0, 1) }); _lines[0] = new LogLine(0, 0, "Hello World!", LevelFlags.None); logFile.OnLogFileModified(_source.Object, LogFileSection.Invalidate(0, 1)); _taskScheduler.RunOnce(); logFile.Count.Should().Be(0); logFile.OnLogFileModified(_source.Object, new LogFileSection(0, 1)); _taskScheduler.RunOnce(); logFile.Count.Should().Be(1); _changes.Should().Equal(new object[] { LogFileSection.Reset, new LogFileSection(0, 1), LogFileSection.Invalidate(0, 1), new LogFileSection(0, 1) }); logFile.GetLine(0).Should().Be(new LogLine(0, 0, "Hello World!", LevelFlags.None)); }
public void TestReadOneLine4() { _streamWriter.Write("A"); _streamWriter.Flush(); _scheduler.RunOnce(); _streamWriter.Write("B"); _streamWriter.Flush(); _scheduler.RunOnce(); _streamWriter.Write("C"); _streamWriter.Flush(); _scheduler.RunOnce(); _changes.Should().Equal(new object[] { LogFileSection.Reset, new LogFileSection(0, 1), LogFileSection.Invalidate(0, 1), new LogFileSection(0, 1), LogFileSection.Invalidate(0, 1), new LogFileSection(0, 1) }, "because the log file should've sent invalidations for the 2nd and 3rd read (because the same line was modified)"); _file.Count.Should().Be(1); _file.GetLine(0).Should().Be(new LogLine(0, 0, "ABC", LevelFlags.None)); }
public void TestTwoEntries1() { var logFile = new MultiLineLogFile(_taskScheduler, _source.Object, TimeSpan.Zero); _lines.Add(new LogLine(0, 0, "DEBUG: Starting...", LevelFlags.Debug)); logFile.OnLogFileModified(_source.Object, new LogFileSection(0, 1)); _taskScheduler.RunOnce(); logFile.AddListener(_listener.Object, TimeSpan.Zero, 10); _lines.Add(new LogLine(1, 1, "INFO: hello", LevelFlags.Info)); logFile.OnLogFileModified(_source.Object, new LogFileSection(1, 1)); _taskScheduler.RunOnce(); _changes.Should().Equal(new object[] { LogFileSection.Reset, new LogFileSection(0, 1), new LogFileSection(1, 1) }); _changes.Clear(); _lines.Add(new LogLine(2, 2, "world!", LevelFlags.None)); logFile.OnLogFileModified(_source.Object, new LogFileSection(2, 1)); _taskScheduler.RunOnce(); _changes.Should().Equal(new object[] { LogFileSection.Invalidate(1, 1), new LogFileSection(1, 2) }); }
public void TestManyEntries4() { var logFile = new MultiLineLogFile(_taskScheduler, _source.Object, TimeSpan.Zero); _lines.Add(new LogLine(0, 0, "Foo", LevelFlags.None)); _lines.Add(new LogLine(1, 1, "INFO: Bar", LevelFlags.Info)); logFile.OnLogFileModified(_source.Object, new LogFileSection(0, 2)); _taskScheduler.RunOnce(); logFile.GetSection(new LogFileSection(0, 2)) .Should().Equal(new object[] { new LogLine(0, 0, "Foo", LevelFlags.None), new LogLine(1, 1, "INFO: Bar", LevelFlags.Info) }); logFile.OnLogFileModified(_source.Object, LogFileSection.Invalidate(1, 1)); _taskScheduler.RunOnce(); logFile.Count.Should().Be(1); _lines[1] = new LogLine(1, 1, "Bar", LevelFlags.None); _lines.Add(new LogLine(2, 2, "INFO: Sup", LevelFlags.Info)); logFile.OnLogFileModified(_source.Object, new LogFileSection(1, 2)); _taskScheduler.RunOnce(); logFile.Count.Should().Be(3); logFile.GetSection(new LogFileSection(0, 3)) .Should().Equal(new object[] { new LogLine(0, 0, "Foo", LevelFlags.None), new LogLine(1, 0, "Bar", LevelFlags.None), new LogLine(2, 1, "INFO: Sup", LevelFlags.Info) }); }
public void TestSingleLineFilter6() { var filter = new EmptyLogLineFilter(); using (var file = new FilteredLogFile(_taskScheduler, TimeSpan.Zero, _logFile.Object, filter, null)) { _entries.Add(new LogLine(0, 0, "DEBUG: This is a test", LevelFlags.Debug)); _entries.Add(new LogLine(1, 1, "More stuff", LevelFlags.Debug)); _entries.Add(new LogLine(2, 2, "", LevelFlags.Debug)); _entries.Add(new LogLine(3, 3, "And even more stuff", LevelFlags.Debug)); _entries.Add(new LogLine(4, 4, "And even more stuff", LevelFlags.Debug)); file.OnLogFileModified(_logFile.Object, new LogFileSection(0, 5)); _taskScheduler.RunOnce(); file.OnLogFileModified(_logFile.Object, LogFileSection.Invalidate(3, 2)); _taskScheduler.RunOnce(); file.OnLogFileModified(_logFile.Object, new LogFileSection(3, 2)); _taskScheduler.RunOnce(); file.Count.Should().Be(4, "because the source represents 4 lines (of which the last two changed over its lifetime)"); const string reason = "because log entry indices are supposed to be consecutive for a data source"; file.GetLine(0).LogEntryIndex.Should().Be(0, reason); file.GetLine(1).LogEntryIndex.Should().Be(1, reason); file.GetLine(2).LogEntryIndex.Should().Be(2, reason); file.GetLine(3).LogEntryIndex.Should().Be(3, reason); } }
public void TestManyEntries7() { var logFile = new MultiLineLogFile(_taskScheduler, _source.Object, TimeSpan.Zero); logFile.AddListener(_listener.Object, TimeSpan.Zero, 3); _lines.Add(new LogLine(0, 0, "A", LevelFlags.None)); logFile.OnLogFileModified(_source.Object, new LogFileSection(0, 1)); _taskScheduler.RunOnce(); _lines.Add(new LogLine(1, 1, "B", LevelFlags.Info)); logFile.OnLogFileModified(_source.Object, new LogFileSection(1, 1)); _taskScheduler.RunOnce(); _lines[1] = new LogLine(1, 1, "B", LevelFlags.None); _lines.Add(new LogLine(2, 2, "C", LevelFlags.None)); logFile.OnLogFileModified(_source.Object, LogFileSection.Invalidate(1, 1)); logFile.OnLogFileModified(_source.Object, new LogFileSection(1, 2)); _taskScheduler.RunOnce(); logFile.GetSection(new LogFileSection(0, 3)) .Should().Equal( new LogLine(0, 0, "A", LevelFlags.None), new LogLine(1, 1, "B", LevelFlags.None), new LogLine(2, 2, "C", LevelFlags.None)); }
public void TestSplitInvalidateGreaterThanThreshold([Values(2, 99, 100)] int count) { int maxCount = count - 1; var section = LogFileSection.Invalidate(new LogLineIndex(42), count); section.Split(maxCount).Should().Equal(new[] { section }, "because invalidations are NEVER split up"); }
public void TestInvalidateThenAppendWithGap() { var changes = new MergedLogFileChanges(10); changes.InvalidateFrom(5); changes.Append(7, 10); changes.Sections.Should().Equal(new object[] { LogFileSection.Invalidate(5, 5), new LogFileSection(5, 12) }); }
public void TestInvalidate1() { var notifier = new LogFileListenerNotifier(_logFile.Object, _listener.Object, TimeSpan.Zero, 1); notifier.OnRead(1); notifier.Invalidate(0, 1); _changes.Should().Equal(new[] { LogFileSection.Reset, new LogFileSection(0, 1), LogFileSection.Invalidate(0, 1) }); notifier.LastNumberOfLines.Should().Be(0); }
public void TestInvalidate() { var changes = new MergedLogFileChanges(42); changes.InvalidateFrom(10); changes.Sections.Should().Equal(new object[] { LogFileSection.Invalidate(10, 32) }); changes.TryGetFirstInvalidationIndex(out var index).Should().BeTrue(); index.Should().Be(new LogLineIndex(10)); }
public void TestInvalidateTwiceSuperfluous() { var changes = new MergedLogFileChanges(13); changes.InvalidateFrom(5); changes.InvalidateFrom(7); changes.Sections.Should().Equal(new object[] { LogFileSection.Invalidate(5, 8) }); changes.TryGetFirstInvalidationIndex(out var index).Should().BeTrue(); index.Should().Be(new LogLineIndex(5)); }
public void Invalidate(int firstIndex, int count) { int lastIndex = Math.Min(firstIndex + count, _lastNumberOfLines); int invalidateCount = lastIndex - firstIndex; // When the start index of the invalidation is greater than the last reported index // then this means that our listeners haven't even gotten the change yet and thus // they don't need to be notified of the invalidation either. if (invalidateCount > 0) { var section = LogFileSection.Invalidate(firstIndex, invalidateCount); _listener.OnLogFileModified(_logFile, section); _lastNumberOfLines = firstIndex; } }
public void TestInvalidateThenAppend() { var changes = new MergedLogFileChanges(10); changes.InvalidateFrom(5); changes.Append(5, 6); changes.Sections.Should().Equal(new object[] { LogFileSection.Invalidate(5, 5), new LogFileSection(5, 6) }); changes.TryGetFirstInvalidationIndex(out var index).Should().BeTrue(); index.Should().Be(new LogLineIndex(5)); }
public void TestInvalidate2() { var notifier = new LogFileListenerNotifier(_logFile.Object, _listener.Object, TimeSpan.FromSeconds(1), 10); notifier.OnRead(10); notifier.OnRead(12); notifier.Invalidate(0, 12); _changes.Should().Equal(new[] { LogFileSection.Reset, new LogFileSection(0, 10), LogFileSection.Invalidate(0, 10) }, "Because the notifier should've reported only the first 10 changes and therefore Invalidate() only had to invalidate those 10 changes" ); notifier.LastNumberOfLines.Should().Be(0); }
public void InvalidateFrom(LogLineIndex firstInvalidIndex) { if (firstInvalidIndex >= _count) { Log.WarnFormat("Ignoring invalidation from index '{0}' onwards because nothing has been appended there!", firstInvalidIndex); return; } if (firstInvalidIndex >= _initialCount) { // We do not need to add an invalidation, rather we can simply clamp an existing previous append if (firstInvalidIndex > 0) { var previous = _changes[_changes.Count - 1]; if (!previous.IsInvalidate && !previous.IsReset) { var gap = previous.Index + previous.Count - firstInvalidIndex; if (gap > 0) { previous.Count -= gap; _changes[_changes.Count - 1] = previous; } } } } else { var invalidationCount = _count - firstInvalidIndex; if (_invalidationIndex != -1) { var invalidation = _changes[_invalidationIndex]; if (invalidation.Index <= firstInvalidIndex) { return; //< Nothing to do } _changes[_invalidationIndex] = LogFileSection.Invalidate(firstInvalidIndex, invalidationCount); } else { _invalidationIndex = _changes.Count; _changes.Add(LogFileSection.Invalidate(firstInvalidIndex, invalidationCount)); } } }
public void TestOneLine1() { var logFile = new MultiLineLogFile(_taskScheduler, _source.Object, TimeSpan.Zero); _lines.Add(new LogLine(0, 0, "INFO: Hello ", LevelFlags.Info)); logFile.OnLogFileModified(_source.Object, new LogFileSection(0, 1)); _taskScheduler.RunOnce(); logFile.Count.Should().Be(1); logFile.GetLine(0).Should().Be(new LogLine(0, 0, "INFO: Hello ", LevelFlags.Info)); _lines[0] = new LogLine(0, 0, "INFO: Hello World!", LevelFlags.Info); logFile.OnLogFileModified(_source.Object, LogFileSection.Invalidate(0, 1)); _taskScheduler.RunOnce(); logFile.Count.Should().Be(0); logFile.OnLogFileModified(_source.Object, new LogFileSection(0, 1)); _taskScheduler.RunOnce(); logFile.Count.Should().Be(1); logFile.GetLine(0).Should().Be(new LogLine(0, 0, "INFO: Hello World!", LevelFlags.Info)); }
public void TestListen3() { using (var proxy = new LogFileProxy(_scheduler, TimeSpan.Zero, _logFile.Object)) { proxy.AddListener(_listener.Object, TimeSpan.Zero, 1000); _listeners.OnRead(500); _listeners.Invalidate(400, 100); _listeners.OnRead(550); _scheduler.RunOnce(); _modifications.Should().Equal(new[] { LogFileSection.Reset, new LogFileSection(0, 500), LogFileSection.Invalidate(400, 100), new LogFileSection(400, 150) }); } }
public void TestInvalidate2() { using (var file = new FilteredLogFile(_taskScheduler, TimeSpan.Zero, _logFile.Object, null, Filter.Create(null, true, LevelFlags.Info))) { file.AddListener(_listener.Object, TimeSpan.Zero, 1); _taskScheduler.RunOnce(); file.EndOfSourceReached.Should().BeTrue(); _entries.AddRange(new[] { new LogLine(0, 0, "A", LevelFlags.Info), new LogLine(1, 1, "B", LevelFlags.Info), new LogLine(2, 2, "C", LevelFlags.Info), new LogLine(3, 3, "D", LevelFlags.Info) }); file.OnLogFileModified(_logFile.Object, new LogFileSection(0, 4)); _taskScheduler.RunOnce(); file.EndOfSourceReached.Should().BeTrue(); file.Count.Should().Be(4); file.OnLogFileModified(_logFile.Object, LogFileSection.Invalidate(2, 2)); _taskScheduler.RunOnce(); file.EndOfSourceReached.Should().BeTrue(); file.Count.Should().Be(2); _sections.Should().Equal(new[] { LogFileSection.Reset, new LogFileSection(0, 1), new LogFileSection(1, 1), new LogFileSection(2, 1), new LogFileSection(3, 1), LogFileSection.Invalidate(2, 2) }); } }
public void TestAppendTwoSourcesWrongOrderSeparateChangesFullInvalidation() { var source1 = new InMemoryLogFile(); source1.AddEntry("B", LevelFlags.None, new DateTime(2019, 5, 27, 23, 10, 0)); var source2 = new InMemoryLogFile(); source2.AddEntry("A", LevelFlags.None, new DateTime(2019, 5, 27, 23, 09, 0)); var index = new MergedLogFileIndex(source1, source2); var changes = index.Process(new MergedLogFilePendingModification(source1, new LogFileSection(0, 1))); changes.Should().Equal(new object[] { new LogFileSection(0, 1) }); changes = index.Process(new MergedLogFilePendingModification(source2, new LogFileSection(0, 1))); changes.Should().Equal(new object[] { LogFileSection.Invalidate(0, 1), new LogFileSection(0, 2) }); var indices = index.Get(new LogFileSection(0, 2)); indices.Count.Should().Be(2); indices[0].LogFileIndex.Should().Be(1); indices[0].SourceLineIndex.Should().Be(0); indices[0].OriginalLogEntryIndex.Should().Be(0); indices[0].MergedLogEntryIndex.Should().Be(0); indices[0].Timestamp.Should().Be(new DateTime(2019, 5, 27, 23, 9, 0)); indices[1].LogFileIndex.Should().Be(0); indices[1].SourceLineIndex.Should().Be(0); indices[1].OriginalLogEntryIndex.Should().Be(0); indices[1].MergedLogEntryIndex.Should().Be(1); indices[1].Timestamp.Should().Be(new DateTime(2019, 5, 27, 23, 10, 0)); }
public void TestInvalidate1() { using (var file = new FilteredLogFile(_taskScheduler, TimeSpan.Zero, _logFile.Object, null, Filter.Create(null, true, LevelFlags.Info))) { _taskScheduler.RunOnce(); file.EndOfSourceReached.Should().BeTrue(); _entries.AddRange(new[] { new LogLine(0, 0, "A", LevelFlags.Info), new LogLine(1, 1, "B", LevelFlags.Info), new LogLine(2, 2, "C", LevelFlags.Info), new LogLine(3, 3, "D", LevelFlags.Info) }); file.OnLogFileModified(_logFile.Object, new LogFileSection(0, 4)); file.OnLogFileModified(_logFile.Object, LogFileSection.Invalidate(2, 2)); _taskScheduler.RunOnce(); file.EndOfSourceReached.Should().BeTrue(); file.Count.Should().Be(2, "because we've invalidated the last 2 out of 4 lines"); } }
public void TestToString() { LogFileSection.Reset.ToString().Should().Be("Reset"); LogFileSection.Invalidate(42, 5).ToString().Should().Be("Invalidated [#42, #5]"); }