public void GetMessageRange( bool isGloballyEnabled, LogMessageField enabledSpecificFilters, LogMessageField matchingSpecificFilters, MatchBehavior matchBehavior, double startIdRatio, double endIdRatio) { CreateFilterAndReferencePredicate( isGloballyEnabled, enabledSpecificFilters, matchingSpecificFilters, matchBehavior, out var collection, out var filter, out var unfilteredMessages, out var filteredMessages); // calculate the id where to start/end searching long startId = (long)(startIdRatio * (unfilteredMessages.Length - 1)); long endId = (long)(endIdRatio * (unfilteredMessages.Length - 1)); // determine the messages that is expected to be returned var expectedMessages = filteredMessages .Where(message => message.Id >= startId && message.Id <= endId) .ToList(); using (collection) using (filter) { var found = filter.GetMessageRange(startId, endId); Assert.Equal(expectedMessages, found); } }
public void GetPreviousMessages( bool isGloballyEnabled, LogMessageField enabledSpecificFilters, LogMessageField matchingSpecificFilters, MatchBehavior matchBehavior, double startIdRatio, int count, bool reverse) { CreateFilterAndReferencePredicate( isGloballyEnabled, enabledSpecificFilters, matchingSpecificFilters, matchBehavior, out var collection, out var filter, out var unfilteredMessages, out var filteredMessages); // calculate the id where to start searching long startId = (long)(startIdRatio * (unfilteredMessages.Length - 1)); // determine the messages that is expected to be returned var expectedMessages = new List <LogFileMessage>(); foreach (var message in filteredMessages) { if (message.Id > startId) { break; } expectedMessages.Add(message); } // remove superfluous messages and reverse the result list, if necessary expectedMessages.RemoveRange(0, Math.Max(expectedMessages.Count - count, 0)); if (!reverse) { expectedMessages.Reverse(); } using (collection) using (filter) { var found = filter.GetPreviousMessages(startId, count, reverse); Assert.Equal(expectedMessages, found); } }
public void GetNextMessage( bool isGloballyEnabled, LogMessageField enabledSpecificFilters, LogMessageField matchingSpecificFilters, MatchBehavior matchBehavior, double startIdRatio) { CreateFilterAndReferencePredicate( isGloballyEnabled, enabledSpecificFilters, matchingSpecificFilters, matchBehavior, out var collection, out var filter, out var unfilteredMessages, out var filteredMessages); // calculate the id where to start searching long startId = (long)(startIdRatio * (unfilteredMessages.Length - 1)); // determine the message that is expected to be returned LogFileMessage expectedMessage = null; // assume no match at start, revise later for (int i = filteredMessages.Length - 1; i >= 0; i--) { var message = filteredMessages[i]; if (message.Id < startId) { break; } expectedMessage = message; } using (collection) using (filter) { var found = filter.GetNextMessage(startId); Assert.Equal(expectedMessage, found); } }
/// <summary> /// Creates a <see cref="FileBackedLogMessageCollection"/>, attaches a <see cref="SelectableFileBackedLogMessageFilter"/> /// to it and configures it for various test cases. /// </summary> /// <param name="isGloballyEnabled"> /// <c>true</c> to enable the filter globally (specific filters are in effect); /// <c>false</c> to disable the filter globally (all messages bypass specific filters). /// </param> /// <param name="enabledSpecificFilters">Enabled specific filters (flags).</param> /// <param name="matchingSpecificFilters">Specific filters that should be configured to match (flags).</param> /// <param name="matchBehavior">Determines how to select matching messages.</param> /// <param name="collection">Receives the created collection the filter works on.</param> /// <param name="filter">Receives the created filter.</param> /// <param name="unfilteredMessages">Receives messages that have been put into the collection.</param> /// <param name="filteredMessages">Receives messages that pass the filter.</param> private void CreateFilterAndReferencePredicate( bool isGloballyEnabled, LogMessageField enabledSpecificFilters, LogMessageField matchingSpecificFilters, MatchBehavior matchBehavior, out FileBackedLogMessageCollection collection, out SelectableFileBackedLogMessageFilter filter, out LogFileMessage[] unfilteredMessages, out LogFileMessage[] filteredMessages) { // create collection and attach a filter to it collection = CreateCollection(500, out var generatedMessages); unfilteredMessages = generatedMessages.Cast <LogFileMessage>().ToArray(); filter = new SelectableFileBackedLogMessageFilter { Enabled = isGloballyEnabled }; filter.AttachToCollection(collection); var firstMessage = unfilteredMessages[0]; var lastMessage = unfilteredMessages[unfilteredMessages.Length - 1]; // -------------------------------------------------------------------------------------------------------- // configure timestamp filter // -------------------------------------------------------------------------------------------------------- DateTimeOffset from, to; filter.TimestampFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.Timestamp); if (matchingSpecificFilters.HasFlag(LogMessageField.Timestamp)) { // filter should match if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // match starting at the first message from = to = collection[0].Timestamp; } else { // match starting at the second message from = to = collection[1].Timestamp; } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // match up to the last message to = collection[collection.Count - 1].Timestamp; } else if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // match up to the second last message to = collection[collection.Count - 2].Timestamp; } filter.TimestampFilter.From = from; filter.TimestampFilter.To = to; } else { // filter should not match // => choose interval from last message (+ margin) to 'infinity' from = collection[collection.Count - 1].Timestamp + TimeSpan.FromMilliseconds(1); to = DateTimeOffset.MaxValue; filter.TimestampFilter.From = from; filter.TimestampFilter.To = to; } // -------------------------------------------------------------------------------------------------------- // configure application name filter // -------------------------------------------------------------------------------------------------------- filter.ApplicationNameFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.ApplicationName); bool applicationNameSelected = matchingSpecificFilters.HasFlag(LogMessageField.ApplicationName); var selectedApplicationNames = new HashSet <string>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the application name matching the first message in the set var specificFilter = filter .ApplicationNameFilter .Items .First(x => x.Value == firstMessage.ApplicationName); specificFilter.Selected = applicationNameSelected; if (applicationNameSelected) { selectedApplicationNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the application name matching the last message in the set var specificFilter = filter .ApplicationNameFilter .Items .First(x => x.Value == lastMessage.ApplicationName); specificFilter.Selected = applicationNameSelected; if (applicationNameSelected) { selectedApplicationNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select an application name matching messages in between, but surely not the first or the last one var specificFilter = filter .ApplicationNameFilter .Items .First(x => x.Value != firstMessage.ApplicationName && x.Value != lastMessage.ApplicationName); specificFilter.Selected = applicationNameSelected; if (applicationNameSelected) { selectedApplicationNames.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure process name filter // -------------------------------------------------------------------------------------------------------- filter.ProcessNameFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.ProcessName); bool processNameSelected = matchingSpecificFilters.HasFlag(LogMessageField.ProcessName); var selectedProcessNames = new HashSet <string>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the process name matching the first message in the set var specificFilter = filter .ProcessNameFilter .Items .First(x => x.Value == firstMessage.ProcessName); specificFilter.Selected = processNameSelected; if (processNameSelected) { selectedProcessNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the process name matching the last message in the set var specificFilter = filter .ProcessNameFilter .Items .First(x => x.Value == lastMessage.ProcessName); specificFilter.Selected = processNameSelected; if (processNameSelected) { selectedProcessNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select a process name matching messages in between, but surely not the first or the last one var specificFilter = filter .ProcessNameFilter .Items .First(x => x.Value != firstMessage.ProcessName && x.Value != lastMessage.ProcessName); specificFilter.Selected = processNameSelected; if (processNameSelected) { selectedProcessNames.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure process id filter // -------------------------------------------------------------------------------------------------------- filter.ProcessIdFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.ProcessId); bool processIdSelected = matchingSpecificFilters.HasFlag(LogMessageField.ProcessId); var selectedProcessIds = new HashSet <int>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the process id matching the first message in the set var specificFilter = filter .ProcessIdFilter .Items .First(x => x.Value == firstMessage.ProcessId); specificFilter.Selected = processIdSelected; if (processIdSelected) { selectedProcessIds.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the process id matching the last message in the set var specificFilter = filter .ProcessIdFilter .Items .First(x => x.Value == lastMessage.ProcessId); specificFilter.Selected = processIdSelected; if (processIdSelected) { selectedProcessIds.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select a process id matching messages in between, but surely not the first or the last one var specificFilter = filter .ProcessIdFilter .Items .First(x => x.Value != firstMessage.ProcessId && x.Value != lastMessage.ProcessId); specificFilter.Selected = processIdSelected; if (processIdSelected) { selectedProcessIds.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure log level filter // -------------------------------------------------------------------------------------------------------- filter.LogLevelFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.LogLevelName); bool logLevelSelected = matchingSpecificFilters.HasFlag(LogMessageField.LogLevelName); var selectedLogLevelNames = new HashSet <string>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the log level matching the first message in the set var specificFilter = filter .LogLevelFilter .Items .First(x => x.Value == firstMessage.LogLevelName); specificFilter.Selected = logLevelSelected; if (logLevelSelected) { selectedLogLevelNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the log level matching the last message in the set var specificFilter = filter .LogLevelFilter .Items .First(x => x.Value == lastMessage.LogLevelName); specificFilter.Selected = logLevelSelected; if (logLevelSelected) { selectedLogLevelNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select a log level matching messages in between, but surely not the first or the last one var specificFilter = filter .LogLevelFilter .Items .First(x => x.Value != firstMessage.LogLevelName && x.Value != lastMessage.LogLevelName); specificFilter.Selected = logLevelSelected; if (logLevelSelected) { selectedLogLevelNames.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure log writer filter // -------------------------------------------------------------------------------------------------------- filter.LogWriterFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.LogWriterName); bool logWriterSelected = matchingSpecificFilters.HasFlag(LogMessageField.LogWriterName); var selectedLogWriterNames = new HashSet <string>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the log writer name matching the first message in the set var specificFilter = filter .LogWriterFilter .Items .First(x => x.Value == firstMessage.LogWriterName); specificFilter.Selected = logWriterSelected; if (logWriterSelected) { selectedLogWriterNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the log writer name matching the last message in the set var specificFilter = filter .LogWriterFilter .Items .First(x => x.Value == lastMessage.LogWriterName); specificFilter.Selected = logWriterSelected; if (logWriterSelected) { selectedLogWriterNames.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select a log writer matching messages in between, but surely not the first or the last one var specificFilter = filter .LogWriterFilter .Items .First(x => x.Value != firstMessage.LogWriterName && x.Value != lastMessage.LogWriterName); specificFilter.Selected = logWriterSelected; if (logWriterSelected) { selectedLogWriterNames.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure tag filter // -------------------------------------------------------------------------------------------------------- filter.TagFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.Tags); bool tagSelected = matchingSpecificFilters.HasFlag(LogMessageField.Tags); var selectedTags = new HashSet <string>(); if (matchBehavior.HasFlag(MatchBehavior.MatchFirst)) { // select the tag matching the first message in the set var specificFilter = filter .TagFilter .Items .First(x => firstMessage.Tags.Contains(x.Value)); specificFilter.Selected = tagSelected; if (tagSelected) { selectedTags.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchLast)) { // select the tag matching the last message in the set // (may also match the first as multiple tags can be attached to a message) var specificFilter = filter .TagFilter .Items .First(x => lastMessage.Tags.Contains(x.Value)); specificFilter.Selected = tagSelected; if (tagSelected) { selectedTags.Add(specificFilter.Value); } } if (matchBehavior.HasFlag(MatchBehavior.MatchInBetween)) { // select the tag matching messages in between, but surely not the first or the last one var specificFilter = filter .TagFilter .Items .First(x => !firstMessage.Tags.Contains(x.Value) && !lastMessage.Tags.Contains(x.Value)); specificFilter.Selected = tagSelected; if (tagSelected) { selectedTags.Add(specificFilter.Value); } } // -------------------------------------------------------------------------------------------------------- // configure text filter // (filtering for the first/last message or in-between is very difficult...) // -------------------------------------------------------------------------------------------------------- string searchText = matchingSpecificFilters.HasFlag(LogMessageField.Text) ? "1/a" : "~~~"; filter.TextFilter.Enabled = enabledSpecificFilters.HasFlag(LogMessageField.Text); filter.TextFilter.IsCaseSensitive = true; filter.TextFilter.SearchText = searchText; const bool isFilterCaseSensitive = true; // -------------------------------------------------------------------------------------------------------- // create predicate matching messages // -------------------------------------------------------------------------------------------------------- bool Predicate(LogFileMessage message) { // bypass specific filters when the global filter switch is disabled if (!isGloballyEnabled) { return(true); } if (enabledSpecificFilters.HasFlag(LogMessageField.Timestamp)) { // the filter selects all messages except the first and the last message in the collection if (message.Timestamp < from || message.Timestamp > to) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.ApplicationName)) { if (!selectedApplicationNames.Contains(message.ApplicationName)) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.ProcessName)) { if (!selectedProcessNames.Contains(message.ProcessName)) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.ProcessId)) { if (!selectedProcessIds.Contains(message.ProcessId)) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.LogLevelName)) { if (!selectedLogLevelNames.Contains(message.LogLevelName)) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.LogWriterName)) { if (!selectedLogWriterNames.Contains(message.LogWriterName)) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.Tags)) { if (!selectedTags.Any(x => message.Tags.Contains(x))) { return(false); } } if (enabledSpecificFilters.HasFlag(LogMessageField.Text)) { if (CultureInfo.InvariantCulture.CompareInfo.IndexOf(message.Text, searchText, isFilterCaseSensitive ? CompareOptions.None : CompareOptions.IgnoreCase) < 0) { return(false); } } return(true); } filteredMessages = unfilteredMessages.Where(Predicate).ToArray(); }
public SkipValidationIfAnotherValueMatchesAttribute() { ValueProviderKey = null; RegexPattern = null; Behavior = MatchBehavior.SkipIfWholeInputMatches; }