private static ILogBuffer Listen(ILogSource logSource) { var data = new LogBufferList(logSource.Columns); var listener = new Mock <ILogSourceListener>(); listener.Setup(x => x.OnLogFileModified(It.IsAny <ILogSource>(), It.IsAny <LogSourceModification>())) .Callback((ILogSource file, LogSourceModification modification) => { if (modification.IsReset()) { data.Clear(); } else if (modification.IsRemoved(out var removedSection)) { data.RemoveRange((int)removedSection.Index, removedSection.Count); } else if (modification.IsAppended(out var appendedSection)) { var destinationIndex = data.Count; data.Resize(data.Count + appendedSection.Count); file.GetEntries(appendedSection, data, destinationIndex); } }); logSource.AddListener(listener.Object, TimeSpan.Zero, 1); return(data); }
public void TestCopyFromArray_PartiallyFilled() { var entries = new LogBufferList(Core.Columns.LogLevel); entries.Add(new ReadOnlyLogEntry(new Dictionary <IColumnDescriptor, object> { { Core.Columns.LogLevel, LevelFlags.Info } })); entries.Add(new ReadOnlyLogEntry(new Dictionary <IColumnDescriptor, object> { { Core.Columns.LogLevel, LevelFlags.Trace } })); var buffer = new LevelFlags[] { LevelFlags.All, LevelFlags.Debug, LevelFlags.Error, LevelFlags.Warning }; entries.Resize(4); entries.Count.Should().Be(buffer.Length); entries.CopyFrom(Core.Columns.LogLevel, 0, buffer, 0, buffer.Length); entries[0].LogLevel.Should().Be(LevelFlags.All, "because the first entry's level should have been overwritten"); entries[1].LogLevel.Should().Be(LevelFlags.Debug, "because the second entry's level should have been overwritten"); entries[2].LogLevel.Should().Be(LevelFlags.Error, "because the third log entry should been added"); entries[3].LogLevel.Should().Be(LevelFlags.Warning, "because the third log entry should been added"); }
public void TestFill_NullColumn() { var buffer = new LogBufferList(Core.Columns.LineNumber); buffer.Resize(10); new Action(() => buffer.Fill(null, 42, 2, 4)).Should().Throw <ArgumentNullException>(); }
public void TestResizeAddRows() { var entries = new LogBufferList(Core.Columns.RawContent); entries.Add(new ReadOnlyLogEntry(new Dictionary <IColumnDescriptor, object> { { Core.Columns.RawContent, "Hello!" } })); entries.Resize(3); entries.Count.Should().Be(3); entries[0].RawContent.Should().Be("Hello!", "because the content of the first cell should have been left untouched"); entries[1].RawContent.Should().BeNull("because an default value should have been placed in the newly added cell"); entries[2].RawContent.Should().BeNull("because an default value should have been placed in the newly added cell"); }
public void TestFillInvalidLength() { var buffer = new LogBufferList(Core.Columns.LineNumber); buffer.Resize(10); buffer.Fill(Core.Columns.LineNumber, 42, 0, 10); new Action(() => buffer.Fill(Core.Columns.LineNumber, 9001, 0, 11)) .Should().Throw <ArgumentException>(); for (int i = 0; i < 10; ++i) { buffer[i].LineNumber.Should().Be(42, "because nothing may have been overwritten"); } }
public void TestResizeRemoveRows() { var entries = new LogBufferList(Core.Columns.RawContent); entries.Add(new ReadOnlyLogEntry(new Dictionary <IColumnDescriptor, object> { { Core.Columns.RawContent, "Hello," } })); entries.Add(new ReadOnlyLogEntry(new Dictionary <IColumnDescriptor, object> { { Core.Columns.RawContent, "World!" } })); entries.Resize(1); entries.Count.Should().Be(1, "because we just removed a cell"); entries[0].RawContent.Should().Be("Hello,", "Because the content of the first cell should been left untouched"); }
public void TestResizeInvalidCount() { var entries = new LogBufferList(Core.Columns.RawContent); entries.Add(new ReadOnlyLogEntry(new Dictionary <IColumnDescriptor, object> { { Core.Columns.RawContent, "Hello," } })); entries.Add(new ReadOnlyLogEntry(new Dictionary <IColumnDescriptor, object> { { Core.Columns.RawContent, "World!" } })); new Action(() => entries.Resize(-1)).Should().Throw <ArgumentOutOfRangeException>(); entries.Count.Should().Be(2, "because the list shouldn't have been modified"); entries[0].RawContent.Should().Be("Hello,", "Because the content of the first cell should been left untouched"); entries[1].RawContent.Should().Be("World!", "Because the content of the second cell should been left untouched"); }
public void TestFill() { var buffer = new LogBufferList(Core.Columns.LineNumber); buffer.Resize(10); buffer.Fill(Core.Columns.LineNumber, 42, 2, 4); buffer.Fill(Core.Columns.LineNumber, 1337, 7, 2); buffer[0].LineNumber.Should().Be(Core.Columns.LineNumber.DefaultValue); buffer[1].LineNumber.Should().Be(Core.Columns.LineNumber.DefaultValue); buffer[2].LineNumber.Should().Be(42); buffer[3].LineNumber.Should().Be(42); buffer[4].LineNumber.Should().Be(42); buffer[5].LineNumber.Should().Be(42); buffer[6].LineNumber.Should().Be(Core.Columns.LineNumber.DefaultValue); buffer[7].LineNumber.Should().Be(1337); buffer[8].LineNumber.Should().Be(1337); buffer[9].LineNumber.Should().Be(Core.Columns.LineNumber.DefaultValue); }
public void TestCopyFromArray_Empty() { var entries = new LogBufferList(Core.Columns.LogLevel); var buffer = new LevelFlags[] { LevelFlags.All, LevelFlags.Debug, LevelFlags.Error, LevelFlags.Warning }; entries.Resize(4); entries.Count.Should().Be(buffer.Length); entries.CopyFrom(Core.Columns.LogLevel, 0, buffer, 0, buffer.Length); entries[0].LogLevel.Should().Be(LevelFlags.All); entries[1].LogLevel.Should().Be(LevelFlags.Debug); entries[2].LogLevel.Should().Be(LevelFlags.Error); entries[3].LogLevel.Should().Be(LevelFlags.Warning); }
public void TestContainsAny() { var buffer = new LogBufferList(Core.Columns.LineNumber); buffer.Resize(3); buffer[0].LineNumber = 1; buffer[1].LineNumber = 2; buffer[2].LineNumber = 3; buffer.ContainsAny(Core.Columns.LineNumber, 1, new Int32Range(0, 1)).Should().BeTrue(); buffer.ContainsAny(Core.Columns.LineNumber, 1, new Int32Range(0, 2)).Should().BeTrue(); buffer.ContainsAny(Core.Columns.LineNumber, 1, new Int32Range(0, 3)).Should().BeTrue(); buffer.ContainsAny(Core.Columns.LineNumber, 1, new Int32Range(1, 1)).Should().BeFalse(); buffer.ContainsAny(Core.Columns.LineNumber, 1, new Int32Range(1, 2)).Should().BeFalse(); buffer.ContainsAny(Core.Columns.LineNumber, 1, new Int32Range(2, 1)).Should().BeFalse(); buffer.ContainsAny(Core.Columns.LineNumber, 2, new Int32Range(0, 3)).Should().BeTrue(); buffer.ContainsAny(Core.Columns.LineNumber, 2, new Int32Range(0, 1)).Should().BeFalse(); buffer.ContainsAny(Core.Columns.LineNumber, 2, new Int32Range(2, 1)).Should().BeFalse(); }
public void UpdateVisibleLines() { _visibleTextLines.Clear(); if (_logSource == null) { return; } try { _visibleBufferBuffer.Clear(); _visibleBufferBuffer.Resize(_currentlyVisibleSection.Count); if (_currentlyVisibleSection.Count > 0) { // We don't want to block the UI thread for very long at all so we instruct the log source to only // fetch data from the cache, but to fetch missing data for later (from the source). var queryOptions = new LogSourceQueryOptions(LogSourceQueryMode.FromCache | LogSourceQueryMode.FetchForLater, TimeSpan.Zero); _logSource.GetEntries(_currentlyVisibleSection, _visibleBufferBuffer, 0, queryOptions); // Now comes the fun part. We need to detect if we could fetch *all* the data. // This is done by inspecting the BufferedLogSource.RetrievalState - if we encounter any NotCached value, // then the entry is part of the source, but was not cached at the time of trying to access it. // If that's the case, we will instruct this canvas to re-fetch the once more in a bit. This loop will terminate once the // cache has managed to fetch the desired data which should happen some time... if (_visibleBufferBuffer.ContainsAny(PageBufferedLogSource.RetrievalState, RetrievalState.NotCached, new Int32Range(offset: 0, _currentlyVisibleSection.Count))) { if (!_requiresFurtherUpdate) { Log.DebugFormat("Requires further update (at least one entry is not in cache)"); _requiresFurtherUpdate = true; _updateStart = DateTime.Now; } } else { if (_requiresFurtherUpdate) { var elapsed = DateTime.Now - _updateStart; Log.DebugFormat("No longer requires further update (all retrieved log entries are in cache), took {0:F1}ms", elapsed.TotalMilliseconds); _requiresFurtherUpdate = false; } } for (int i = 0; i < _currentlyVisibleSection.Count; ++i) { var line = new TextLine(_visibleBufferBuffer[i], _hoveredIndices, _selectedIndices, _colorByLevel, _textSettings, _textBrushes) { IsFocused = IsFocused, SearchResults = _searchResults }; _visibleTextLines.Add(line); } } Action fn = VisibleLinesChanged; fn?.Invoke(); InvalidateVisual(); } catch (ArgumentOutOfRangeException e) { Log.DebugFormat("Caught exception while trying to update text: {0}", e); } catch (IndexOutOfRangeException e) { Log.DebugFormat("Caught exception while trying to update text: {0}", e); } }