Example #1
0
        public void TestNoData()
        {
            var buffer = new PagedLogBuffer(1024, 10, Core.Columns.RawContent);

            buffer.ResizeTo(12);

            var destination = new LogBufferArray(12, PageBufferedLogSource.RetrievalState, Core.Columns.RawContent);

            destination[0].RawContent  = "Foo";
            destination[1].RawContent  = "Bar";
            destination[10].RawContent = "Big Smoke";
            destination[11].RawContent = "Sup";
            buffer.TryGetEntries(new LogSourceSection(0, 10), destination, 1).Should().BeFalse("because the cache is completely empty and thus no data should have been retrieved");

            destination[0].RawContent.Should()
            .Be("Foo",
                "because only the data from the specified offset onward may have been overwritten");
            for (int i = 1; i < 11; ++i)
            {
                destination[i].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotCached);
                destination[i].RawContent.Should().Be(Core.Columns.RawContent.DefaultValue,
                                                      "because when the region couldn't be read from the cache, then it should have been defaulted");
            }
            destination[11].RawContent.Should().Be("Sup");
        }
Example #2
0
        public void TestRequestPartiallyCached_Segmented_ReadFromTwoPages()
        {
            var buffer = new PagedLogBuffer(1024, 10, Core.Columns.RawContent);

            buffer.ResizeTo(12);

            var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent)
            {
                new LogEntry(),
                new LogEntry {
                    RawContent = "Dina",
                },
                new LogEntry {
                    RawContent = "Jesse"
                }
            };

            buffer.TryAdd(new LogSourceSection(7, 2), data, 1);

            var destination = new LogBufferArray(11, Core.Columns.Index, Core.Columns.RawContent);

            buffer.TryGetEntries(new LogSourceSection(4, 5), destination, 6).Should().BeFalse("because we managed to only retrieve the data partially");


            for (int i = 6; i < 9; ++i)
            {
                destination[i].Index.Should().Be(Core.Columns.Index.DefaultValue);
                destination[i].RawContent.Should().Be(Core.Columns.RawContent.DefaultValue);
            }

            destination[9].Index.Should().Be(7);
            destination[9].RawContent.Should().Be("Dina");
            destination[10].Index.Should().Be(8);
            destination[10].RawContent.Should().Be("Jesse");
        }
Example #3
0
        public void TestCopyFromUnknownColumn()
        {
            var buffer = new LogBufferArray(2, Core.Columns.Timestamp);

            new Action(() => buffer.CopyFrom(Core.Columns.RawContent, 0, new string[0], 0, 0))
            .Should().Throw <NoSuchColumnException>();
        }
Example #4
0
        public void TestTryGetEntries_DestinationTooSmall()
        {
            var buffer = new PagedLogBuffer(4, 2, Core.Columns.RawContent);

            buffer.ResizeTo(4);
            var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent)
            {
                new LogEntry {
                    RawContent = "A"
                },
                new LogEntry {
                    RawContent = "B"
                },
                new LogEntry {
                    RawContent = "C"
                },
                new LogEntry {
                    RawContent = "D"
                }
            };

            buffer.TryAdd(new LogSourceSection(0, 8), data, 0);

            var destination = new LogBufferArray(2, Core.Columns.Index, Core.Columns.RawContent);

            destination[0].RawContent = "1";
            destination[1].RawContent = "2";
            new Action(() => buffer.TryGetEntries(new LogSourceSection(0, 2), destination, 1))
            .Should().Throw <ArgumentException>("because the destination is too small");

            destination[0].RawContent.Should().Be("1", "because the original data may not have been overwritten");
            destination[1].RawContent.Should().Be("2", "because the original data may not have been overwritten");
        }
Example #5
0
        public void Export(IProgress <Percentage> progressReporter = null)
        {
            const int bufferSize = 1000;
            var       buffer     = new LogBufferArray(bufferSize, Columns.Index, Columns.RawContent);
            var       count      = _logSource.GetProperty(Properties.LogEntryCount);
            var       index      = 0;

            using (var writer = new StreamWriter(_stream, Encoding.UTF8, 1024, true))
            {
                while (index < count)
                {
                    var remaining = count - index;
                    if (remaining > bufferSize)
                    {
                        remaining = bufferSize;
                    }
                    if (!ExportPortion(writer, buffer, index, remaining))
                    {
                        break;
                    }

                    index += remaining;
                    var progress = Percentage.Of(index, count);
                    progressReporter?.Report(progress);
                }
            }
        }
Example #6
0
        private bool ExportPortion(StreamWriter writer, LogBufferArray array, int index, int count)
        {
            try
            {
                _logSource.GetEntries(new LogSourceSection(index, count), array);

                for (var i = 0; i < count; ++i)
                {
                    if (_written)
                    {
                        writer.WriteLine();
                    }

                    var logLine = array[i];
                    if (logLine.Index == LogLineIndex.Invalid)                     //< EOF
                    {
                        break;
                    }

                    writer.Write(logLine.RawContent);
                    _written = true;
                }

                return(true);
            }
            catch (IndexOutOfRangeException)
            {
                // The file has been invalidated and reduced in size already.
                // That's okay and we can end this export....
                return(false);
            }
        }
Example #7
0
        public void TestCopyFromNullColumn()
        {
            var buffer = new LogBufferArray(2, Core.Columns.Timestamp);

            new Action(() => buffer.CopyFrom(null, 0, new string[0], 0, 0))
            .Should().Throw <ArgumentNullException>();
        }
        public PresentationLogSource(ITaskScheduler scheduler, ILogSource source, TimeSpan maximumWaitTime, TextSettings textSettings)
            : base(scheduler)
        {
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            _maximumWaitTime = maximumWaitTime;
            _textSettings    = textSettings;
            _source          = source;

            _indices = new LogBufferList(IndexedColumns);

            _array = new LogBufferArray(MaximumLineCount, Core.Columns.RawContent);
            _pendingModifications = new ConcurrentQueue <PendingModification>();
            _syncRoot             = new object();

            _source.AddListener(this, _maximumWaitTime, MaximumLineCount);
            StartTask();
        }
Example #9
0
        public LogSourceSearch(ITaskScheduler taskScheduler, ILogSource logSource, string searchTerm, TimeSpan maximumWaitTime)
        {
            if (taskScheduler == null)
            {
                throw new ArgumentNullException(nameof(taskScheduler));
            }
            if (logSource == null)
            {
                throw new ArgumentNullException(nameof(logSource));
            }
            if (string.IsNullOrEmpty(searchTerm))
            {
                throw new ArgumentException("searchTerm may not be empty");
            }

            _logSource            = logSource;
            _filter               = new SubstringFilter(searchTerm, true);
            _matches              = new List <LogMatch>();
            _syncRoot             = new object();
            _listeners            = new LogFileSearchListenerCollection(this);
            _pendingModifications = new ConcurrentQueue <LogSourceModification>();
            _scheduler            = taskScheduler;

            const int maximumLineCount = 1000;

            _maximumWaitTime = maximumWaitTime;
            _logLinesArray   = new LogBufferArray(maximumLineCount, Columns.Index, Columns.RawContent);
            _matchesBuffer   = new List <LogLineMatch>();
            _logSource.AddListener(this, _maximumWaitTime, maximumLineCount);

            _task = _scheduler.StartPeriodic(FilterAllPending,
                                             TimeSpan.FromMilliseconds(100),
                                             string.Format("Search {0}", logSource));
        }
Example #10
0
        protected override IReadOnlyLogEntry CreateEmpty()
        {
            // TODO: Swap
            var buffer = new LogBufferArray(1);

            return(buffer[0]);
        }
Example #11
0
        protected override IReadOnlyLogEntry CreateDefault()
        {
            // TODO: Swap
            var buffer = new LogBufferArray(1, Core.Columns.Minimum);

            return(buffer[0]);
        }
        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");
        }
Example #13
0
        public void TestRequestFullyCached_Contiguous_ReadFromMultiplePages()
        {
            var buffer = new PagedLogBuffer(1024, 10, Core.Columns.RawContent);

            var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent);

            for (int i = 0; i < 5 * 1024; ++i)
            {
                data.Add(new LogEntry {
                    Index = i, RawContent = i.ToString()
                });
            }
            buffer.ResizeTo(data.Count);
            buffer.TryAdd(new LogSourceSection(0, data.Count), data, 0);

            var destination = new LogBufferArray(2048, Core.Columns.Index, Core.Columns.RawContent);
            var readOffset  = 1024;

            buffer.TryGetEntries(new LogSourceSection(readOffset, destination.Count), destination, 0).Should().BeTrue("because all requested data is part of the cache");

            for (int i = 0; i < destination.Count; ++i)
            {
                var logEntry = destination[i];
                logEntry.Index.Should().Be(readOffset + i);
                logEntry.RawContent.Should().Be((readOffset + i).ToString());
            }
        }
Example #14
0
        public void TestRetrieveFromPartiallyFilledPage_CreatedBeforeResize()
        {
            var buffer = new PagedLogBuffer(10, 1, Core.Columns.RawContent);

            buffer.ResizeTo(2);
            var data = new LogBufferList(Core.Columns.RawContent)
            {
                new LogEntry {
                    RawContent = "A"
                },
                new LogEntry {
                    RawContent = "B"
                }
            };

            buffer.TryAdd(new LogSourceSection(0, 2), data, 0);
            buffer.ResizeTo(4);

            var destination = new LogBufferArray(6, PageBufferedLogSource.RetrievalState, Core.Columns.RawContent);

            buffer.TryGetEntries(new LogSourceSection(0, 6), destination, 0).Should().BeFalse("because the cache is only partially filled");

            destination[0].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.Retrieved);
            destination[1].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.Retrieved);
            destination[2].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotCached);
            destination[3].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotCached);
            destination[4].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotInSource);
            destination[5].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotInSource);
        }
Example #15
0
        public void TestConstruction2([Values(1, 2, 5, 10, 42, 100, 9001)] int count)
        {
            var buffer = new LogBufferArray(count);

            buffer.Columns.Should().BeEmpty();
            buffer.Count.Should().Be(count);
            buffer.Should().HaveCount(count);
        }
Example #16
0
        public void TestCopyFrom()
        {
            var buffer    = new LogBufferArray(1, Core.Columns.Timestamp);
            var timestamp = new DateTime(2017, 12, 11, 21, 41, 0);

            buffer.CopyFrom(Core.Columns.Timestamp, new DateTime?[] { timestamp });
            buffer[0].Timestamp.Should().Be(timestamp, "Because we've just copied this timestamp to the buffer");
        }
Example #17
0
        public void TestGetEntryByIndex1([Values(-1, 0, 1)] int invalidIndex)
        {
            var buffer = new LogBufferArray(0);

            new Action(() =>
            {
                var unused = buffer[invalidIndex];
            }).Should().Throw <IndexOutOfRangeException>();
        }
Example #18
0
        public void TestIgnoreDataOutOfBounds()
        {
            var buffer = new PagedLogBuffer(4, 2, Core.Columns.RawContent);

            buffer.ResizeTo(4);
            var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent)
            {
                new LogEntry {
                    RawContent = "A"
                },
                new LogEntry {
                    RawContent = "B"
                },
                new LogEntry {
                    RawContent = "C"
                },
                new LogEntry {
                    RawContent = "D"
                },
                new LogEntry {
                    RawContent = "E"
                },
                new LogEntry {
                    RawContent = "F"
                },
                new LogEntry {
                    RawContent = "G"
                },
                new LogEntry {
                    RawContent = "H"
                },
            };

            buffer.TryAdd(new LogSourceSection(0, 8), data, 0);

            var destination = new LogBufferArray(8, Core.Columns.Index, PageBufferedLogSource.RetrievalState, Core.Columns.RawContent);

            buffer.TryGetEntries(new LogSourceSection(0, 8), destination, 0).Should().BeFalse("because even though we've tried to add 8 elements to the buffer, only the first 4 are part of the entire log file section and thus the others should have been ignored");

            destination[0].RawContent.Should().Be("A");
            destination[1].RawContent.Should().Be("B");
            destination[2].RawContent.Should().Be("C");
            destination[3].RawContent.Should().Be("D");

            for (int i = 0; i < 4; ++i)
            {
                destination[i].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.Retrieved);
            }


            for (int i = 4; i < 8; ++i)
            {
                destination[i].RawContent.Should().Be(Core.Columns.RawContent.DefaultValue);
                destination[i].GetValue(PageBufferedLogSource.RetrievalState).Should().Be(RetrievalState.NotInSource);
            }
        }
Example #19
0
        public void TestCopyFromPartial3()
        {
            var buffer = new LogBufferArray(2, Core.Columns.Timestamp);

            var timestamp = new DateTime(2017, 12, 11, 21, 41, 0);

            buffer.CopyFrom(Core.Columns.Timestamp, 1, new DateTime?[] { timestamp }, 0, 1);
            buffer[0].Timestamp.Should().BeNull("because we didn't copy any data for this timestamp");
            buffer[1].Timestamp.Should().Be(timestamp, "Because we've just copied this timestamp to the buffer");
        }
        public void TestSkipSourceIfNotAllowed()
        {
            var buffer       = new PageBufferedLogSource(_taskScheduler, _source.Object, TimeSpan.Zero);
            var destination  = new LogBufferArray(4, new IColumnDescriptor[] { Core.Columns.Index, Core.Columns.RawContent });
            var queryOptions = new LogSourceQueryOptions(LogSourceQueryMode.FromCache);

            buffer.GetEntries(new LogSourceSection(10, 4), 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 the data to be retrieved from the source under any circumstances");
        }
Example #21
0
        public void TestConstruction3([Values(1, 2, 5, 10, 42, 100, 9001)] int count)
        {
            var buffer = new LogBufferArray(count, new List <IColumnDescriptor> {
                Core.Columns.RawContent, Core.Columns.DeltaTime
            });

            buffer.Columns.Should().Equal(new object[] { Core.Columns.RawContent, Core.Columns.DeltaTime });
            buffer.Count.Should().Be(count);
            buffer.Should().HaveCount(count);
        }
        public void TestFetchFromSourceWhenNotAllowedFromCache()
        {
            var buffer       = new PageBufferedLogSource(_taskScheduler, _source.Object, TimeSpan.Zero);
            var destination  = new LogBufferArray(4, new IColumnDescriptor[] { Core.Columns.Index, Core.Columns.RawContent });
            var queryOptions = new LogSourceQueryOptions(LogSourceQueryMode.FromSource);

            buffer.GetEntries(new LogSourceSection(10, 4), destination, 0, queryOptions);
            _source.Verify(x => x.GetEntries(new LogSourceSection(10, 4), destination, 0, queryOptions),
                           Times.Once);
        }
Example #23
0
        public void TestCopyFromManyRows()
        {
            const int count  = 1000;
            var       buffer = new LogBufferArray(count, Core.Columns.OriginalIndex);

            buffer.CopyFrom(Core.Columns.OriginalIndex, Enumerable.Range(0, count).Select(i => (LogLineIndex)i).ToArray());
            for (int i = 0; i < count; ++i)
            {
                buffer[i].OriginalIndex.Should().Be(i);
            }
        }
Example #24
0
        public void TestCopyFromOverwrite()
        {
            var buffer = new LogBufferArray(2, Core.Columns.RawContent);

            buffer[0].RawContent.Should().BeNull();
            buffer[1].RawContent.Should().BeNull();

            buffer.CopyFrom(Core.Columns.RawContent, new [] { "foo", "bar" });
            buffer[0].RawContent.Should().Be("foo");
            buffer[1].RawContent.Should().Be("bar");
        }
Example #25
0
        public void TestContainsColumn()
        {
            var buffer = new LogBufferArray(42, new IColumnDescriptor[] { Core.Columns.LogLevel, Core.Columns.Index, Core.Columns.RawContent });

            buffer.Contains(Core.Columns.LogLevel).Should().BeTrue();
            buffer.Contains(Core.Columns.Index).Should().BeTrue();
            buffer.Contains(Core.Columns.RawContent).Should().BeTrue();

            buffer.Contains(Core.Columns.Message).Should().BeFalse();
            buffer.Contains(Core.Columns.OriginalLineNumber).Should().BeFalse();
            buffer.Contains(Core.Columns.DeltaTime).Should().BeFalse();
        }
Example #26
0
        public void TestAccessUnavailableColumn()
        {
            var buffer = new LogBufferArray(1);

            new Action(() => { var unused = buffer[0].RawContent; }).Should().Throw <ColumnNotRetrievedException>();
            new Action(() => { var unused = buffer[0].Index; }).Should().Throw <ColumnNotRetrievedException>();
            new Action(() => { var unused = buffer[0].OriginalIndex; }).Should().Throw <ColumnNotRetrievedException>();
            new Action(() => { var unused = buffer[0].LineNumber; }).Should().Throw <ColumnNotRetrievedException>();
            new Action(() => { var unused = buffer[0].OriginalLineNumber; }).Should().Throw <ColumnNotRetrievedException>();
            new Action(() => { var unused = buffer[0].Timestamp; }).Should().Throw <ColumnNotRetrievedException>();
            new Action(() => { var unused = buffer[0].ElapsedTime; }).Should().Throw <ColumnNotRetrievedException>();
            new Action(() => { var unused = buffer[0].DeltaTime; }).Should().Throw <ColumnNotRetrievedException>();
        }
Example #27
0
        public void TestFillInvalidLength()
        {
            var buffer = new LogBufferArray(10, Core.Columns.LineNumber);

            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");
            }
        }
Example #28
0
        public void TestReadPreviouslyInvalidatedButNowAvailableRegions_PartialPageEviction()
        {
            var buffer = new PagedLogBuffer(4, 2, Core.Columns.RawContent);

            buffer.ResizeTo(16);
            var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent)
            {
                new LogEntry {
                    RawContent = "A"
                },
                new LogEntry {
                    RawContent = "B"
                },
                new LogEntry {
                    RawContent = "C"
                },
                new LogEntry {
                    RawContent = "D"
                },
                new LogEntry {
                    RawContent = "E"
                },
                new LogEntry {
                    RawContent = "F"
                },
                new LogEntry {
                    RawContent = "G"
                },
                new LogEntry {
                    RawContent = "H"
                },
            };

            buffer.TryAdd(new LogSourceSection(0, 8), data, 0);

            buffer.ResizeTo(6);
            buffer.ResizeTo(8);

            var destination = new LogBufferArray(8, Core.Columns.Index, Core.Columns.RawContent);

            buffer.TryGetEntries(new LogSourceSection(0, 8), destination, 0).Should().BeFalse("because the data has been partially invalidated");

            destination[0].RawContent.Should().Be("A");
            destination[1].RawContent.Should().Be("B");
            destination[2].RawContent.Should().Be("C");
            destination[3].RawContent.Should().Be("D");
            destination[4].RawContent.Should().Be("E");
            destination[5].RawContent.Should().Be("F");
            destination[6].RawContent.Should().Be(Core.Columns.RawContent.DefaultValue, "because this row has been invalidated when the log source was downsized");
            destination[7].RawContent.Should().Be(Core.Columns.RawContent.DefaultValue, "because this row has been invalidated when the log source was downsized");
        }
Example #29
0
        public void TestRequestFullyCached_Contiguous()
        {
            var buffer = new PagedLogBuffer(1024, 10, Core.Columns.RawContent);

            buffer.ResizeTo(12);

            var data = new LogBufferList(Core.Columns.Index, Core.Columns.RawContent)
            {
                new LogEntry {
                    Index = 2, RawContent = "Scrambled Data",
                },
                new LogEntry {
                    Index = 3, RawContent = "This is awesome"
                },
                new LogEntry {
                    Index = 4, RawContent = "Yup"
                },
                new LogEntry {
                    Index = 5, RawContent = "Twist!"
                },
                new LogEntry {
                    Index = 10, RawContent = "I shouldn't be cached"
                }
            };

            buffer.TryAdd(new LogSourceSection(3, 3), data, 1);

            var destination = new LogBufferArray(5, Core.Columns.Index, Core.Columns.RawContent);

            destination[0].Index      = 32;
            destination[0].RawContent = "Foo";
            destination[1].Index      = 42;
            destination[1].RawContent = "Bar";
            destination[4].Index      = 9001;
            destination[4].RawContent = "His power level is over 9000!";
            buffer.TryGetEntries(new LogSourceSection(3, 2), destination, 2).Should().BeTrue();
            destination[0].Index.Should().Be(32, "because we specified an offset and the data before it should not have been overwritten");
            destination[0].RawContent.Should().Be("Foo", "because we specified an offset and the data before it should not have been overwritten");
            destination[1].Index.Should().Be(42, "because we specified an offset and the data before it should not have been overwritten");
            destination[1].RawContent.Should().Be("Bar", "because we specified an offset and the data before it should not have been overwritten");

            destination[2].Index.Should().Be(data[1].Index);
            destination[2].RawContent.Should().Be(data[1].RawContent);
            destination[3].Index.Should().Be(data[2].Index);
            destination[3].RawContent.Should().Be(data[2].RawContent);

            destination[4].Index.Should().Be(9001, "because the data after the requested region shouldn't have been overwritten");
            destination[4].RawContent.Should().Be("His power level is over 9000!", "because the data after the requested region shouldn't have been overwritten");
        }
Example #30
0
        public void TestCopyFromMultipleColumns()
        {
            var buffer = new LogBufferArray(2,
                                            Core.Columns.Index,
                                            Core.Columns.Timestamp);

            buffer.CopyFrom(Core.Columns.Index, new LogLineIndex[] { 1, 42 });
            buffer.CopyFrom(Core.Columns.Timestamp, new DateTime?[] { DateTime.MinValue, DateTime.MaxValue });

            buffer[0].Index.Should().Be(1);
            buffer[0].Timestamp.Should().Be(DateTime.MinValue);

            buffer[1].Index.Should().Be(42);
            buffer[1].Timestamp.Should().Be(DateTime.MaxValue);
        }