public void TestTail_WriteOneLineTwoFlushes_Changes3() { var encoding = Encoding.UTF8; var fileName = GetUniqueNonExistingFileName(); var linePart1 = "The sky"; var linePart2 = " Crawlers"; using (var stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var writer = new StreamWriter(stream, encoding)) using (var logFile = Create(fileName, encoding)) { var changes = AddListener(logFile, 1000); changes.Should().Equal(new object[] { LogSourceModification.Reset() }); writer.Write(linePart1); writer.Flush(); _taskScheduler.RunOnce(); changes.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1) }, "because the file consists of one line"); writer.Write(linePart2); writer.Flush(); _taskScheduler.RunOnce(); changes.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1), LogSourceModification.Removed(0, 1), LogSourceModification.Appended(0, 1) }); } }
public void TestTail_WriteTwoLines_Changes1() { var encoding = Encoding.UTF8; var fileName = GetUniqueNonExistingFileName(); var line1 = "The sky crawlers"; var line2 = "is awesome!"; using (var stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var writer = new StreamWriter(stream, encoding)) using (var logFile = Create(fileName, encoding)) { var changes = AddListener(logFile, 1000); changes.Should().Equal(new object[] { LogSourceModification.Reset() }); writer.Write(line1 + "\r\n"); writer.Flush(); _taskScheduler.RunOnce(); changes.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1), LogSourceModification.Appended(1, 1) }, "because the file consists of two lines, one being totally empty"); writer.Write(line2 + "\r\n"); writer.Flush(); _taskScheduler.RunOnce(); changes.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1), LogSourceModification.Appended(1, 1), LogSourceModification.Removed(1, 1), LogSourceModification.Appended(1, 2) }); } }
public void TestTail_WriteTwoLines_Changes2() { var encoding = Encoding.UTF8; var fileName = GetUniqueNonExistingFileName(); var line1 = "The sky crawlers"; var line2 = "is awesome!"; using (var stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var writer = new StreamWriter(stream, encoding)) using (var logFile = Create(fileName, encoding)) { var changes = AddListener(logFile, 1000); changes.Should().Equal(new object[] { LogSourceModification.Reset() }); writer.Write(line1); writer.Flush(); _taskScheduler.RunOnce(); changes.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1) }, "because the file consists of one line"); writer.Write("\n" + line2); writer.Flush(); _taskScheduler.RunOnce(); //changes.Should().Equal(new object[] {LogSourceModification.Reset(), new LogFileSection(0, 1), new LogFileSection(1, 1)}); // The current behavior won't cause wrong behavior in upstream listeners, but it will cause them unnecessary work. changes.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1), LogSourceModification.Removed(0, 1), LogSourceModification.Appended(0, 2) }); } }
public void TestInvokeListenerEventually() { var line = "Hello, World!"; var fileName = GetUniqueNonExistingFileName(); using (var stream = File.OpenWrite(fileName)) using (var writer = new StreamWriter(stream)) { writer.Write(line); } var logFile = Create(fileName, new UTF8Encoding(true)); var listener = new Mock <ILogSourceListener>(); var modifications = new List <LogSourceModification>(); listener.Setup(x => x.OnLogFileModified(logFile, It.IsAny <LogSourceModification>())) .Callback((ILogSource _, LogSourceModification modification) => { modifications.Add(modification); }); var maxWaitTime = TimeSpan.FromMilliseconds(500); logFile.AddListener(listener.Object, maxWaitTime, 500); modifications.Should().Equal(new object[] { LogSourceModification.Reset() }); _taskScheduler.RunOnce(); logFile.GetProperty(Properties.LogEntryCount).Should().Be(1, "because there's one log entry in the file"); modifications.Should().Equal(new object[] { LogSourceModification.Reset() }, "because not enough time has elapsed and thus the log source may not have notified the listener just yet"); Thread.Sleep(maxWaitTime); _taskScheduler.RunOnce(); logFile.GetProperty(Properties.LogEntryCount).Should().Be(1, "because there's still one log entry in the file"); modifications.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1) }, "because enough time has passed for the log file to notify us at this point in time"); }
public void AddListener(ILogSourceListener listener, TimeSpan maximumWaitTime, int maximumLineCount) { if (_listeners.Add(listener)) { listener.OnLogFileModified(this, LogSourceModification.Reset()); } }
public void TestEquality() { var appendModification = LogSourceModification.Appended(10, 41); var equalAppendModification = LogSourceModification.Appended(10, 41); var anotherAppendModification = LogSourceModification.Appended(9, 41); appendModification.Should().Be(equalAppendModification); equalAppendModification.Should().Be(appendModification); appendModification.Should().NotBe(anotherAppendModification); anotherAppendModification.Should().NotBe(equalAppendModification); var removedModification = LogSourceModification.Removed(10, 41); appendModification.Should().NotBe(removedModification); equalAppendModification.Should().NotBe(removedModification); anotherAppendModification.Should().NotBe(removedModification); var anotherRemovedModification = LogSourceModification.Removed(9, 41); removedModification.Should().NotBe(anotherRemovedModification); anotherRemovedModification.Should().NotBe(anotherAppendModification); appendModification.Should().NotBe(LogSourceModification.Reset()); appendModification.Should().NotBe(LogSourceModification.PropertiesChanged()); removedModification.Should().NotBe(LogSourceModification.Reset()); removedModification.Should().NotBe(LogSourceModification.PropertiesChanged()); }
public void TestMergeResetOneSource() { var source1 = new InMemoryLogSource(); var source2 = new InMemoryLogSource(); var merged = new MergedLogSource(_taskScheduler, TimeSpan.Zero, source1, source2); var entries = Listen(merged); var changes = ListenToChanges(merged, 100); source2.AddEntry("a", LevelFlags.Warning, new DateTime(2021, 2, 28, 22, 15, 0)); source1.AddEntry("b", LevelFlags.Info, new DateTime(2021, 2, 28, 22, 16, 0)); source2.AddEntry("c", LevelFlags.Error, new DateTime(2021, 2, 28, 22, 17, 0)); _taskScheduler.RunOnce(); merged.GetProperty(Core.Properties.PercentageProcessed).Should().Be(Percentage.HundredPercent); entries.Count.Should().Be(3); changes.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 3) }); source1.Clear(); _taskScheduler.RunOnce(); entries.Count.Should().Be(2, "because the one entry from source should have been removed from the merged source"); changes.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 3), LogSourceModification.Removed(1, 2), LogSourceModification.Appended(1, 1) }); }
public void TestAppendTwoSourcesWrongOrder() { var source1 = new InMemoryLogSource(); source1.AddEntry("B", LevelFlags.Other, new DateTime(2019, 5, 27, 23, 10, 0)); var source2 = new InMemoryLogSource(); source2.AddEntry("A", LevelFlags.Other, new DateTime(2019, 5, 27, 23, 09, 0)); var index = new MergedLogSourceIndex(source1, source2); var changes = index.Process(new MergedLogSourcePendingModification(source1, LogSourceModification.Appended(0, 1)), new MergedLogSourcePendingModification(source2, LogSourceModification.Appended(0, 1))); changes.Should().Equal(new object[] { LogSourceModification.Appended(0, 2) }); var indices = index.Get(new LogSourceSection(0, 2)); indices.Count.Should().Be(2); indices[0].SourceId.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].SourceId.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 TestFilter2() { using (var file = Create(File20Mb)) { file.Property(x => x.GetProperty(Properties.LogEntryCount)).ShouldAfter(TimeSpan.FromSeconds(10)).Be(165342); using (FilteredLogSource filtered = file.AsFiltered(_taskScheduler, null, Filter.Create("info"))) { var listener = new Mock <ILogSourceListener>(); var modifications = new List <LogSourceModification>(); listener.Setup(x => x.OnLogFileModified(It.IsAny <ILogSource>(), It.IsAny <LogSourceModification>())) .Callback((ILogSource logFile, LogSourceModification modification) => modifications.Add(modification)); filtered.Property(x => x.GetProperty(Properties.LogEntryCount)).ShouldAfter(TimeSpan.FromSeconds(5)).Be(5); filtered.AddListener(listener.Object, TimeSpan.Zero, 1); modifications.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1), LogSourceModification.Appended(1, 1), LogSourceModification.Appended(2, 1), LogSourceModification.Appended(3, 1), LogSourceModification.Appended(4, 1) }); } } }
public void TestPercentageProcessed() { var source = new Mock <ILogSource>(); var sourceProperties = new PropertiesBufferList(); sourceProperties.SetValue(Core.Properties.PercentageProcessed, Percentage.Zero); source.Setup(x => x.Columns).Returns(Core.Columns.Minimum); source.Setup(x => x.GetAllProperties(It.IsAny <IPropertiesBuffer>())) .Callback((IPropertiesBuffer destination) => sourceProperties.CopyAllValuesTo(destination)); source.Setup(x => x.GetProperty(Core.Properties.PercentageProcessed)) .Returns(() => sourceProperties.GetValue(Core.Properties.PercentageProcessed)); source.Setup(x => x.Properties).Returns(() => sourceProperties.Properties); using (var file = Create(source.Object)) { var fileListener = (ILogSourceListener)file; file.GetProperty(Core.Properties.PercentageProcessed).Should().Be(Percentage.Zero, "because the filtered log file hasn't consumed anything of its source (yet)"); _taskScheduler.RunOnce(); file.GetProperty(Core.Properties.PercentageProcessed).Should().Be(Percentage.Zero, "because even though the filter doesn't have anything to do just yet - it's because its own source hasn't even started"); sourceProperties.SetValue(Core.Properties.PercentageProcessed, Percentage.FromPercent(42)); fileListener.OnLogFileModified(source.Object, LogSourceModification.Appended(0, 84)); _taskScheduler.RunOnce(); file.GetProperty(Core.Properties.PercentageProcessed).Should().Be(Percentage.FromPercent(42), "because now the filtered log file has processed 100% of the data the source sent it, but the original data source is still only at 42%"); sourceProperties.SetValue(Core.Properties.PercentageProcessed, Percentage.HundredPercent); fileListener.OnLogFileModified(source.Object, LogSourceModification.Appended(84, 200)); _taskScheduler.RunOnce(); file.GetProperty(Core.Properties.PercentageProcessed).Should().Be(Percentage.HundredPercent); } }
public void TestClear() { var collection = new LogSourceListenerCollection(new Mock <ILogSource>().Object); var listener = new Mock <ILogSourceListener>(); var modifications = new List <LogSourceModification>(); listener.Setup(x => x.OnLogFileModified(It.IsAny <ILogSource>(), It.IsAny <LogSourceModification>())) .Callback((ILogSource file, LogSourceModification y) => modifications.Add(y)); collection.AddListener(listener.Object, TimeSpan.FromHours(1), 1000); collection.OnRead(1); collection.Flush(); modifications.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1), }); collection.Clear(); modifications.Clear(); collection.OnRead(2); collection.Flush(); modifications.Should() .BeEmpty("because the collection should have removed all listeners and thus we may not have been notified anymore"); }
public void TestFlush1() { var collection = new LogSourceListenerCollection(new Mock <ILogSource>().Object); var listener = new Mock <ILogSourceListener>(); var modifications = new List <LogSourceModification>(); listener.Setup(x => x.OnLogFileModified(It.IsAny <ILogSource>(), It.IsAny <LogSourceModification>())) .Callback((ILogSource file, LogSourceModification y) => modifications.Add(y)); collection.AddListener(listener.Object, TimeSpan.FromHours(1), 1000); collection.OnRead(1); modifications.Should().Equal(new object[] { LogSourceModification.Reset() }); collection.Flush(); modifications.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1) }, "Because Flush() should force calling the OnLogFileModified method"); }
public void TestClear() { var source = new InMemoryLogSource(); source.AddEntry("A", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 053)); source.AddEntry("B", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 100)); source.AddEntry("C", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 100)); var index = new MergedLogSourceIndex(source); index.Process(new MergedLogSourcePendingModification(source, LogSourceModification.Appended(0, 3))); index.Count.Should().Be(3); var indices = index.Get(new LogSourceSection(0, 3)); indices[0].SourceLineIndex.Should().Be(0); indices[1].SourceLineIndex.Should().Be(1); indices[2].SourceLineIndex.Should().Be(2); index.Clear(); index.Count.Should().Be(0); indices = index.Get(new LogSourceSection(0, 3)); indices[0].SourceLineIndex.Should().Be(-1); indices[1].SourceLineIndex.Should().Be(-1); indices[2].SourceLineIndex.Should().Be(-1); }
public void TestAppendOneSourceThreeOneLinesOneWithoutTimestamp() { var source = new InMemoryLogSource(); source.AddEntry("A", LevelFlags.Other, new DateTime(2019, 5, 28, 19, 30, 1)); source.AddEntry("B", LevelFlags.Other); source.AddEntry("C", LevelFlags.Other, new DateTime(2019, 5, 28, 19, 30, 42)); var index = new MergedLogSourceIndex(source); var changes = index.Process(new MergedLogSourcePendingModification(source, LogSourceModification.Appended(0, 3))); changes.Should().Equal(new object[] { LogSourceModification.Appended(0, 2) }); index.Count.Should().Be(2); var indices = index.Get(new LogSourceSection(0, 2)); indices.Count.Should().Be(2); indices[0].SourceId.Should().Be(0); 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, 28, 19, 30, 1)); indices[1].SourceId.Should().Be(0); indices[1].SourceLineIndex.Should().Be(2); indices[1].OriginalLogEntryIndex.Should().Be(2); indices[1].MergedLogEntryIndex.Should().Be(1); indices[1].Timestamp.Should().Be(new DateTime(2019, 5, 28, 19, 30, 42)); }
public void TestOneSourceAppendReset() { var source1 = new InMemoryLogSource(); source1.AddEntry("A", LevelFlags.Other, new DateTime(2019, 5, 28, 00, 34, 0)); var index = new MergedLogSourceIndex(source1); var changes = index.Process(new MergedLogSourcePendingModification(source1, LogSourceModification.Appended(0, 1))); changes.Should().Equal(new object[] { LogSourceModification.Appended(0, 1) }); changes = index.Process(new MergedLogSourcePendingModification(source1, LogSourceModification.Reset())); changes.Should().Equal(new object[] { LogSourceModification.Reset() }); index.Count.Should().Be(0); index.Get(new LogSourceSection(0, 1)).Should().Equal(new object[] { MergedLogLineIndex.Invalid }); }
public void TestAddListener1() { var logFile = new InMemoryLogSource(); logFile.AddListener(_listener.Object, TimeSpan.Zero, 1); _modifications.Should().Equal(new object[] { LogSourceModification.Reset() }); }
public void TestAppendTwoSourcesWrongOrderSeparateChangesPartialInvalidation() { var source1 = new InMemoryLogSource(); source1.AddEntry("A", LevelFlags.Other, new DateTime(2019, 5, 28, 00, 34, 0)); source1.AddEntry("C", LevelFlags.Other, new DateTime(2019, 5, 28, 00, 36, 0)); var source2 = new InMemoryLogSource(); source2.AddEntry("B", LevelFlags.Other, new DateTime(2019, 5, 28, 00, 35, 0)); source2.AddEntry("D", LevelFlags.Other, new DateTime(2019, 5, 28, 00, 37, 0)); var index = new MergedLogSourceIndex(source1, source2); var changes = index.Process(new MergedLogSourcePendingModification(source1, LogSourceModification.Appended(0, 2))); changes.Should().Equal(new object[] { LogSourceModification.Appended(0, 2) }); changes = index.Process(new MergedLogSourcePendingModification(source2, LogSourceModification.Appended(0, 2))); changes.Should().Equal(new object[] { LogSourceModification.Removed(1, 1), LogSourceModification.Appended(1, 3) }); }
public void TestAppendOneSourceTwoIdenticalTimestamps() { var source = new InMemoryLogSource(); source.AddEntry("A", LevelFlags.Other, new DateTime(2019, 5, 29, 00, 11, 0)); source.AddEntry("B", LevelFlags.Other, new DateTime(2019, 5, 29, 00, 11, 2)); source.AddEntry("C1", LevelFlags.Other, new DateTime(2019, 5, 29, 00, 11, 4)); source.AddEntry("C2", LevelFlags.Other, new DateTime(2019, 5, 29, 00, 11, 4)); source.AddEntry("D", LevelFlags.Other, new DateTime(2019, 5, 29, 00, 11, 6)); source.AddEntry("E", LevelFlags.Other, new DateTime(2019, 5, 29, 00, 11, 8)); var index = new MergedLogSourceIndex(source); index.Process(new MergedLogSourcePendingModification(source, LogSourceModification.Appended(0, 6))); var indices = index.Get(new LogSourceSection(0, 6)); indices[0].SourceId.Should().Be(0); indices[0].SourceLineIndex.Should().Be(0); indices[1].SourceId.Should().Be(0); indices[1].SourceLineIndex.Should().Be(1); indices[2].SourceId.Should().Be(0); indices[2].SourceLineIndex.Should().Be(2); indices[3].SourceId.Should().Be(0); indices[3].SourceLineIndex.Should().Be(3); indices[4].SourceId.Should().Be(0); indices[4].SourceLineIndex.Should().Be(4); indices[5].SourceId.Should().Be(0); indices[5].SourceLineIndex.Should().Be(5); }
public void TestClear2() { const string fname = "TestClear2.log"; using (FileStream stream = File.OpenWrite(fname)) using (var writer = new StreamWriter(stream)) { stream.SetLength(0); writer.WriteLine("Test"); } using (var logFile = Create(fname)) { var listener = new Mock <ILogSourceListener>(); var modifications = new List <LogSourceModification>(); listener.Setup(x => x.OnLogFileModified(It.IsAny <ILogSource>(), It.IsAny <LogSourceModification>())) .Callback((ILogSource log, LogSourceModification modification) => modifications.Add(modification)); logFile.AddListener(listener.Object, TimeSpan.Zero, 2); logFile.Property(x => x.GetProperty(Properties.LogEntryCount)).ShouldAfter(TimeSpan.FromSeconds(5)).Be(1); using (var stream = new FileStream(fname, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)) { stream.SetLength(0); logFile.Property(x => x.GetProperty(Properties.LogEntryCount)).ShouldAfter(TimeSpan.FromSeconds(5)).Be(0); modifications.Should().EndWith(LogSourceModification.Reset()); } } }
public void TestFollowTail2() { _control.RaiseEvent(new RoutedEventArgs(FrameworkElement.LoadedEvent)); _control.LogSource = _logSource; DispatcherExtensions.ExecuteAllEvents(); var entries = new List <IReadOnlyLogEntry>(); for (int i = 0; i < 51; ++i) { entries.Add(new ReadOnlyLogEntry(new Dictionary <IColumnDescriptor, object> { { Columns.RawContent, "Foobar" }, { Columns.LogLevel, LevelFlags.Info } })); } _logSource.AddRange(entries); Thread.Sleep((int)(2 * LogEntryListView.MaximumRefreshInterval.TotalMilliseconds)); DispatcherExtensions.ExecuteAllEvents(); _control.FollowTail = true; _logSource.Add(new ReadOnlyLogEntry(new Dictionary <IColumnDescriptor, object> { { Columns.RawContent, "Foobar" }, { Columns.LogLevel, LevelFlags.Info } })); _control.OnLogFileModified(_logSource, LogSourceModification.Appended(0, _logSource.Count)); Thread.Sleep((int)(2 * LogEntryListView.MaximumRefreshInterval.TotalMilliseconds)); DispatcherExtensions.ExecuteAllEvents(); _control.VerticalScrollBar.Maximum.Should().Be(15, "Because the view is missing 15 pixels to fully display the last row"); _control.VerticalScrollBar.Value.Should().Be(15, "Because the vertical scrollbar should've moved in order to bring the last line *fully* into view"); }
public void TestReadOneLine4() { _streamWriter.Write("A"); _streamWriter.Flush(); _taskScheduler.RunOnce(); _streamWriter.Write("B"); _streamWriter.Flush(); _taskScheduler.RunOnce(); _streamWriter.Write("C"); _streamWriter.Flush(); _taskScheduler.RunOnce(); _modifications.Should().Equal(new object[] { LogSourceModification.Reset(), LogSourceModification.Appended(0, 1), LogSourceModification.Removed(0, 1), LogSourceModification.Appended(0, 1), LogSourceModification.Removed(0, 1), LogSourceModification.Appended(0, 1) }, "because the log file should've sent invalidations for the 2nd and 3rd read (because the same line was modified)"); _source.GetProperty(Properties.LogEntryCount).Should().Be(1); var entry = _source.GetEntry(0); entry.Index.Should().Be(0); entry.LogEntryIndex.Should().Be(0); entry.RawContent.Should().Be("ABC"); }
public void TestPrefetchAsyncBatch() { var pageSize = 100; var buffer = new PageBufferedLogSource(_taskScheduler, _source.Object, TimeSpan.Zero, pageSize: pageSize); var destination = new LogBufferArray(4, new IColumnDescriptor[] { Core.Columns.Index, Core.Columns.RawContent }); var queryOptions = new LogSourceQueryOptions(LogSourceQueryMode.FromCache | LogSourceQueryMode.FetchForLater); buffer.OnLogFileModified(_source.Object, LogSourceModification.Appended(0, 10)); var section1ToQuery = new LogSourceSection(2, 4); buffer.GetEntries(section1ToQuery, destination, 0, queryOptions); _source.Verify(x => x.GetEntries(It.IsAny <IReadOnlyList <LogLineIndex> >(), It.IsAny <ILogBuffer>(), It.IsAny <int>(), It.IsAny <LogSourceQueryOptions>()), Times.Never, "Because we didn't allow data to be retrieved on the calling thread"); var section2ToQuery = new LogSourceSection(7, 3); buffer.GetEntries(section2ToQuery, destination, 0, queryOptions); _source.Verify(x => x.GetEntries(It.IsAny <IReadOnlyList <LogLineIndex> >(), It.IsAny <ILogBuffer>(), It.IsAny <int>(), It.IsAny <LogSourceQueryOptions>()), Times.Never, "Because we didn't allow data to be retrieved on the calling thread"); _taskScheduler.RunOnce(); _source.Verify(x => x.GetEntries(new LogSourceSection(0, pageSize), It.IsAny <ILogBuffer>(), It.IsAny <int>(), It.IsAny <LogSourceQueryOptions>()), Times.Once, "Because the buffer should avoid reading the same data for the same page multiple times in a row"); }
public void TestDataSourceDoesntExist2() { var dataSource = new Mock <IFileDataSource>(); var logFile = new Mock <ILogSource>(); var emptyReason = new SourceDoesNotExist("E:\\Tailviewer\\somefile.log"); logFile.Setup(x => x.GetProperty(Properties.EmptyReason)).Returns(emptyReason); logFile.Setup(x => x.GetProperty(Properties.Size)).Returns((Size?)null); var filteredLogFile = new Mock <ILogSource>(); ILogSourceListener listener = null; filteredLogFile.Setup(x => x.AddListener(It.IsAny <ILogSourceListener>(), It.IsAny <TimeSpan>(), It.IsAny <int>())) .Callback((ILogSourceListener l, TimeSpan t, int i) => listener = l); dataSource.Setup(x => x.UnfilteredLogSource).Returns(logFile.Object); dataSource.Setup(x => x.FullFileName).Returns(@"E:\Tailviewer\somefile.log"); dataSource.Setup(x => x.FilteredLogSource).Returns(filteredLogFile.Object); dataSource.Setup(x => x.Search).Returns(new Mock <ILogSourceSearch>().Object); var dataSourceModel = CreateFileViewModel(dataSource.Object); var model = new LogViewerViewModel(dataSourceModel, _actionCenter.Object, _settings.Object, TimeSpan.Zero); model.LogEntryCount.Should().Be(0); model.NoEntriesExplanation.Should().Be("Data source does not exist"); model.NoEntriesAction.Should().Be("The data source 'somefile.log' was last seen E:\\Tailviewer"); logFile.Setup(x => x.GetProperty(Properties.EmptyReason)).Returns((IEmptyReason)null); logFile.Setup(x => x.GetProperty(Properties.Size)).Returns(Size.Zero); listener.OnLogFileModified(logFile.Object, LogSourceModification.Appended(0, 0)); model.Update(); model.NoEntriesExplanation.Should().Be("Data source is empty"); model.NoEntriesAction.Should().BeNull(); }
public void TestDeadlockWhenRemovingAnActiveDataSource() { var logFile = new Mock <ILogSource>(); var dataSource = new Mock <IDataSource>(); dataSource.Setup(x => x.UnfilteredLogSource).Returns(logFile.Object); var collection = new BookmarkCollection(_bookmarks.Object, TimeSpan.Zero); logFile.Setup(x => x.RemoveListener(It.IsAny <ILogSourceListener>())) .Callback((ILogSourceListener unused) => { // In order to produce the deadlock, we have to simulate what's happening in reality. // Any ILogFile implementation will hold a lock both while invoking listeners and while // Removing them. Waiting on the OnLogFileModified() call simulates exactly that... var task = new Task(() => { collection.OnLogFileModified(logFile.Object, LogSourceModification.Removed(0, 10)); }, TaskCreationOptions.LongRunning); task.Start(); task.Wait(); }); collection.AddDataSource(dataSource.Object); var removeTask = Task.Factory.StartNew(() => collection.RemoveDataSource(dataSource.Object)); removeTask.Wait(TimeSpan.FromSeconds(1)).Should().BeTrue("because RemoveDataSource should not block at all"); logFile.Verify(x => x.RemoveListener(collection), Times.Once); }
public void TestOneSourceManySameTimestamps() { var source = new InMemoryLogSource(); source.AddEntry("A", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 053)); source.AddEntry("B", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 100)); source.AddEntry("C", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 100)); source.AddEntry("D", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 100)); source.AddEntry("E", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 115)); source.AddEntry("F", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 115)); source.AddEntry("G", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 115)); source.AddEntry("H", LevelFlags.Other, new DateTime(2017, 9, 20, 15, 09, 02, 115)); var index = new MergedLogSourceIndex(source); index.Process(new MergedLogSourcePendingModification(source, LogSourceModification.Appended(0, 8))); var indices = index.Get(new LogSourceSection(0, 8)); indices[0].SourceLineIndex.Should().Be(0); indices[1].SourceLineIndex.Should().Be(1); indices[2].SourceLineIndex.Should().Be(2); indices[3].SourceLineIndex.Should().Be(3); indices[4].SourceLineIndex.Should().Be(4); indices[5].SourceLineIndex.Should().Be(5); indices[6].SourceLineIndex.Should().Be(6); indices[7].SourceLineIndex.Should().Be(7); }
public void TestAddListener() { var logFile = new EmptyLogSource(); var listener = new Mock <ILogSourceListener>(); logFile.AddListener(listener.Object, TimeSpan.Zero, 0); listener.Verify(x => x.OnLogFileModified(logFile, LogSourceModification.Reset()), Times.Once); }
/// <inheritdoc /> public void OnLogFileModified(ILogSource logSource, LogSourceModification modification) { if (Log.IsDebugEnabled) { Log.DebugFormat("OnLogFileModified({0}, {1})", logSource, modification); } _pendingModifications.Enqueue(new MergedLogSourcePendingModification(logSource, modification)); }
public void TestSplitReset([Values(1, 99, 100)] int maxCount) { var section = LogSourceModification.Reset(); section.Split(maxCount).Should().Equal(new[] { section }, "because resets are NEVER split up"); }
/// <inheritdoc /> public void OnLogFileModified(ILogSource logSource, LogSourceModification modification) { if (Log.IsDebugEnabled) { Log.DebugFormat("OnLogFileModified({0}, {1})", logSource, modification); } _pendingSections.Enqueue(new KeyValuePair <ILogSource, LogSourceModification>(logSource, modification)); }
public void TestCurrentLineChanged6() { var notifier = new LogSourceListenerNotifier(_logFile.Object, _listener.Object, TimeSpan.FromHours(1), 1000); notifier.OnRead(-1); _modifications.Should().Equal(new[] { LogSourceModification.Reset() }); }