private static void ValidateFunctionExecutionEventArgumentsList(List <FunctionExecutionEventArguments> list, int noOfFuncExecutions) { FunctionExecutionEventArguments invalidElement = null; string errorMessage = null; Assert.True( ValidateFunctionExecutionEventArgumentsList(list, noOfFuncExecutions, out invalidElement, out errorMessage), string.Format("ErrorMessage:{0} InvalidElement:{1} List:{2}", errorMessage, invalidElement.ToString(), SerializeFunctionExecutionEventArguments(list))); }
private static bool ValidateFunctionExecutionEventArgumentsList(List <FunctionExecutionEventArguments> list, int noOfFuncExecutions, out FunctionExecutionEventArguments invalidElement, out string errorMessage) { invalidElement = new FunctionExecutionEventArguments(); errorMessage = string.Empty; var functionValidationTrackerList = new List <FunctionEventValidationTracker <FunctionExecutionEventArguments> >(); for (int currentIndex = 0; currentIndex < list.Count; currentIndex++) { functionValidationTrackerList.Add(new FunctionEventValidationTracker <FunctionExecutionEventArguments>(list[currentIndex])); } var hashes = new HashSet <string>(); for (int currentIndex = 0; currentIndex < functionValidationTrackerList.Count; currentIndex++) { // The element has not already been processed if (!functionValidationTrackerList[currentIndex].HasBeenProcessed) { var functionExecutionArgs = functionValidationTrackerList[currentIndex].EventArguments; if (hashes.Contains(functionExecutionArgs.InvocationId)) { invalidElement = functionExecutionArgs; errorMessage = "InvocationId has already been used"; return(false); } // If function execution was in progress then there should be a corresponding 'Finished' event if (functionExecutionArgs.ExecutionStage == ExecutionStage.InProgress.ToString()) { List <int> relatedEventIds = new List <int>(); relatedEventIds.Add(currentIndex); for (int secondIndex = currentIndex + 1; secondIndex < functionValidationTrackerList.Count; secondIndex++) { // The element has not already been processed for another function execution and related to the current function invocation event if (!functionValidationTrackerList[secondIndex].HasBeenProcessed && functionValidationTrackerList[secondIndex].EventArguments.FunctionName == functionExecutionArgs.FunctionName && functionValidationTrackerList[secondIndex].EventArguments.InvocationId == functionExecutionArgs.InvocationId) { relatedEventIds.Add(secondIndex); if (functionValidationTrackerList[secondIndex].EventArguments.ExecutionStage == ExecutionStage.Finished.ToString()) { break; } } } if (relatedEventIds.Count < 2) { invalidElement = functionExecutionArgs; errorMessage = "There should be at least one related event"; return(false); } var lastEvent = list[relatedEventIds[relatedEventIds.Count - 1]]; if (lastEvent.ExecutionStage != ExecutionStage.Finished.ToString()) { invalidElement = lastEvent; errorMessage = "Couldn't find Finished event for the current function invocation"; return(false); } else { hashes.Add(lastEvent.InvocationId); } var minEventsExpected = Math.Floor(lastEvent.ExecutionTimeSpan / (double)MinimumLongRunningDurationInMs) - 2; var maxEventsExpected = Math.Ceiling(lastEvent.ExecutionTimeSpan / (double)MinimumLongRunningDurationInMs) + 2; // We should see atleast one InProgress event if it takes more than 5 seconds if (lastEvent.ExecutionTimeSpan >= MinimumLongRunningDurationInMs && (relatedEventIds.Count < minEventsExpected || relatedEventIds.Count > maxEventsExpected)) { invalidElement = lastEvent; errorMessage = string.Format("Long running function doesn't contain expected number of Etw events. Minimum:{0} Maximum:{1} Actual:{2}", minEventsExpected, maxEventsExpected, relatedEventIds.Count); return(false); } foreach (var relatedEventId in relatedEventIds) { // Mark all related events as processed functionValidationTrackerList[relatedEventId].HasBeenProcessed = true; } } else if (functionExecutionArgs.ExecutionStage == ExecutionStage.Finished.ToString()) { functionValidationTrackerList[currentIndex].HasBeenProcessed = true; hashes.Add(functionExecutionArgs.InvocationId); } } } var unprocessedEvents = functionValidationTrackerList.Where(e => !e.HasBeenProcessed).ToList(); if (unprocessedEvents.Count > 0) { invalidElement = unprocessedEvents.FirstOrDefault()?.EventArguments; errorMessage = string.Format("There are unprocessed events: {0}", SerializeFunctionExecutionEventArguments(unprocessedEvents.Select(e => e.EventArguments).ToList())); return(false); } if (hashes.Count != noOfFuncExecutions) { invalidElement = unprocessedEvents.FirstOrDefault()?.EventArguments; errorMessage = string.Format("No of finished events does not match with number of function executions: Expected:{0} Actual:{1}", noOfFuncExecutions, hashes.Count); return(false); } return(true); }