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");
        }
Beispiel #5
0
 public void AddListener(ILogSourceListener listener, TimeSpan maximumWaitTime, int maximumLineCount)
 {
     if (_listeners.Add(listener))
     {
         listener.OnLogFileModified(this, LogSourceModification.Reset());
     }
 }
Beispiel #6
0
        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());
        }
Beispiel #7
0
        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)
                    });
                }
            }
        }
Beispiel #10
0
        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
            });
        }
Beispiel #16
0
        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());
                }
            }
        }
Beispiel #20
0
        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");
        }
Beispiel #21
0
        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");
        }
Beispiel #23
0
        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();
        }
Beispiel #24
0
        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);
        }
Beispiel #26
0
        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);
        }
Beispiel #27
0
        /// <inheritdoc />
        public void OnLogFileModified(ILogSource logSource, LogSourceModification modification)
        {
            if (Log.IsDebugEnabled)
            {
                Log.DebugFormat("OnLogFileModified({0}, {1})", logSource, modification);
            }

            _pendingModifications.Enqueue(new MergedLogSourcePendingModification(logSource, modification));
        }
Beispiel #28
0
        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");
        }
Beispiel #29
0
        /// <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));
        }
Beispiel #30
0
        public void TestCurrentLineChanged6()
        {
            var notifier = new LogSourceListenerNotifier(_logFile.Object, _listener.Object, TimeSpan.FromHours(1), 1000);

            notifier.OnRead(-1);
            _modifications.Should().Equal(new[]
            {
                LogSourceModification.Reset()
            });
        }