private static void ForEach <T>(IList <T> list, AssertDelegate <T> method) { for (int i = 0; i < list.Count; i++) { method(i, list[i]); } }
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="test"></param> /// <param name="actual"></param> /// <param name="expected"></param> /// <param name="itemName"></param> /// <param name="tokenSelector"></param> /// <param name="itemComparer"></param> /// <param name="assert"></param> public static void ValidateSubset <T>(this BaseTest test, IEnumerable <T> actual, IEnumerable <T> expected, string itemName, Func <T, string> tokenSelector, Func <T, T, StringBuilder, bool> itemComparer, AssertDelegate assert) { bool ok = true; StringBuilder logger = new StringBuilder(); List <string> common = new List <string>(); /****************/ foreach (T info in expected) { string token = tokenSelector(info); T[] foundItems = actual.Where(I => tokenSelector(I) == token).ToArray(); if (foundItems.Length == 0) { logger.AppendFormat( "{0} with token '{1}' not found {2}", itemName, token, Environment.NewLine); ok = false; } else { common.Add(token); } } foreach (T info in actual) { string token = tokenSelector(info); T[] foundItems = expected.Where(I => tokenSelector(I) == token).ToArray(); if (foundItems.Length == 0) { logger.AppendFormat( "{0} with token '{1}' not expected {2}", itemName, token, Environment.NewLine); ok = false; } } /****************/ // for common only if (itemComparer != null) { bool local = ArrayUtils.CompareListItems(actual, expected, tokenSelector, common, itemName, logger, itemComparer); ok = ok && local; } assert(ok, logger.ToStringTrimNewLine(), "Check that lists are the same", null); }
public static void CommonGetInfoTestBody <T>(this BaseTest test, Func <List <T> > fullListSelector, Func <string, T> infoSelector, Func <T, string> tokenSelector, Func <T, T, StringBuilder, bool> itemComparison, string itemName, string getInfoMethodName, string getListMethodName, AssertDelegate assert) { // Get valid tokens List <T> infos = fullListSelector(); foreach (T info in infos) { string token = tokenSelector(info); T itemInfo = infoSelector(token); StringBuilder logger = new StringBuilder("Information is different:" + Environment.NewLine); bool tokenOk = true; if (token != tokenSelector(itemInfo)) { tokenOk = false; logger.AppendLine(" Token is different"); } bool ok = itemComparison(info, itemInfo, logger); ok = ok && tokenOk; string stepName = string.Format("Compare {0} got via {1} and via {2}", itemName, getInfoMethodName, getListMethodName); assert(ok, logger.ToStringTrimNewLine(), stepName, string.Empty); } }
public static void ValidateFullRecordingsList(GetRecordingsResponseItem[] fullList, AssertDelegate assert) { // check that tokens are unique bool tokensOk = true; StringBuilder logger = new StringBuilder(); List <string> logged = new List <string>(); foreach (GetRecordingsResponseItem item in fullList) { string token = item.RecordingToken; int count = fullList.Where(RI => RI.RecordingToken == token).Count(); if (count != 1) { tokensOk = false; if (!logged.Contains(token)) { logged.Add(token); logger.AppendFormat("Token '{0}' is not unique{1}", token, Environment.NewLine); } //break; // ? } if (item.Configuration == null) { logger.AppendFormat("Configuration element is missing for item with token '{0}'{1}", token, Environment.NewLine); } } assert(tokensOk, logger.ToStringTrimNewLine(), "Validate recordings list got from GetRecordings", null); }
public static void ValidateSubscription(DateTime?terminationTime, DateTime currentTime, int requestedTerminationTime, Event.EndpointReferenceType subscription, AssertDelegate assert) { assert(terminationTime.HasValue, "TerminationTime is not specified", "Check that TerminationTime is specified", null); if (requestedTerminationTime >= 0) { assert(currentTime.AddSeconds(requestedTerminationTime) <= terminationTime.Value, "TerminationTime < CurrentTime + InitialTerminationTime", "Validate CurrentTime and TerminationTime", null); } else { assert(currentTime < terminationTime.Value, "TerminationTime <= CurrentTime", "Validate CurrentTime and TerminationTime", null); } assert(subscription != null, "The DUT did not return SubscriptionReference", "Check if the DUT returned SubscriptionReference", null); assert(subscription.Address != null && subscription.Address.Value != null, "SubscriptionReference does not contain address", "Check if SubscriptionReference contains address", null); assert(subscription.Address.Value.IsValidUrl(), "URL passed in SubscriptionReference is not valid", "Check that URL specified is valid", null); }
public void GuardedAssert_CallsGuardedFuncIfGuardIsTriggered() { var funcCalled = false; var ass = AssertDelegate.GuardedAssert(() => { funcCalled = true; return(true); }, () => true); Assert.IsTrue(ass()); Assert.IsTrue(funcCalled); }
public void GuardedAssert_DoesNotCallGuardedFuncIfGuardFailsToTrigger() { bool funcCalled = false; var ass = AssertDelegate.GuardedAssert(() => { funcCalled = true; return(true); }, () => false); Assert.IsTrue(ass()); Assert.IsFalse(funcCalled); }
/// <summary> /// Checks that tokens in list are different /// </summary> /// <typeparam name="T">Item type</typeparam> /// <param name="test">Class containing test method in which validation should be performed.</param> /// <param name="list">Items list</param> /// <param name="tokenSelector">Function to get token from Item</param> /// <param name="assert"></param> public static void ValidateTokensInList <T>(this BaseTest test, IEnumerable <T> list, Func <T, string> tokenSelector, AssertDelegate assert) { StringBuilder logger = new StringBuilder(); bool ok = TestUtils.ValidateTokens(list, tokenSelector, logger); assert(ok, logger.ToStringTrimNewLine(), "Check that tokens are unique", string.Empty); }
public static void ValidateSubscription(DateTime?terminationTime, DateTime currentTime, int requestedTerminationTime, Event.EndpointReferenceType subscription, AssertDelegate assert) { assert(terminationTime.HasValue, "TerminationTime is not specified", "Check that TerminationTime is specified", null); bool intervalIsWrong = false; if (currentTime < DateTime.Parse("1970-01-01T00:00:00")) { intervalIsWrong = true; } if (currentTime > DateTime.Parse("2070-01-01T00:00:00")) { intervalIsWrong = true; } if (terminationTime.Value < DateTime.Parse("1970-01-01T00:00:00")) { intervalIsWrong = true; } if (terminationTime.Value > DateTime.Parse("2070-01-01T00:00:00")) { intervalIsWrong = true; } assert(!intervalIsWrong, "TerminationTime or CurrentTime is out of reasonable interval (less than 1970-01-01T00:00:00 or greater than 2070-01-01T00:00:00).", "Check that TerminationTime and CurrentTime has reasonable values", null); if (requestedTerminationTime >= 0) { assert(currentTime.AddSeconds(requestedTerminationTime) <= terminationTime.Value, "TerminationTime < CurrentTime + InitialTerminationTime", "Validate CurrentTime and TerminationTime", null); } else { assert(currentTime < terminationTime.Value, "TerminationTime <= CurrentTime", "Validate CurrentTime and TerminationTime", null); } assert(subscription != null, "The DUT did not return SubscriptionReference", "Check if the DUT returned SubscriptionReference", null); assert(subscription.Address != null && subscription.Address.Value != null, "SubscriptionReference does not contain address", "Check if SubscriptionReference contains address", null); assert(subscription.Address.Value.IsValidUrl(), "URL passed in SubscriptionReference is not valid", "Check that URL specified is valid", null); }
/// <summary> /// Executes user provided method but does not stop the test if the Assertion fails /// </summary> public static void Perform(AssertDelegate assertDelegate, params object[] @objects) { try { assertDelegate(objects); } catch (AssertionException ae) { HandleAssertionException(ae); } }
/// <summary> /// Checks that list contains only one item and this item holds expected information /// </summary> /// <typeparam name="T">Item type</typeparam> /// <param name="test">Class containing test method in which validation should be performed.</param> /// <param name="list">Items list</param> /// <param name="expected"></param> /// <param name="tokenSelector">Function to get token from Item</param> /// <param name="itemComparison">Method for comparing single items.</param> /// <param name="itemName">Name of item for eror description</param> /// <param name="assert"></param> public static void CheckRequestedInfo <T>(this BaseTest test, IEnumerable <T> list, T expected, Func <T, string> tokenSelector, Func <T, T, StringBuilder, bool> itemComparison, string itemName, AssertDelegate assert) { string error = string.Empty; string token = tokenSelector(expected); int count = 0; if (list != null) { count = list.Count(); } if (count == 0) { error = string.Format("No {0} information returned", itemName); } else { if (count > 1) { error = "More than one entry returned"; } else { T item = list.First(); if (tokenSelector(item) != token) { error = "Entry for other token returned"; } else { StringBuilder dump = new StringBuilder("Information is different: " + Environment.NewLine); bool ok = itemComparison(expected, item, dump); if (!ok) { error = dump.ToStringTrimNewLine(); } } } } assert(string.IsNullOrEmpty(error), error, "Check response", string.Empty); }
public static void CommonGetListNoLimitTestBody <T>(this BaseTest test, Func <int> maxLimitSelector, GetListStepMethod <T> listSelector, Func <T, string> tokenSelector, string itemName, AssertDelegate assert) { // Get maxLimit int maxLimit = maxLimitSelector(); List <T> fullList = new List <T>(); List <string> gotByThisMoment = new List <string>(); string offset = null; while (true) { T[] nextPart = null; offset = listSelector(null, offset, out nextPart, string.Format("Get {0} list without limit and start reference ='{1}'", itemName, offset)); int count = nextPart == null ? 0 : nextPart.Length; assert(count <= maxLimit, string.Format("{0} {1}s returned when MaxLimit is {2}", count, itemName, maxLimit), "Check that limit is not exceeded", string.Empty); if (count > 0) { List <string> newTokens = nextPart.Select(tokenSelector).ToList(); test.ValidateNextPart(gotByThisMoment, newTokens, itemName, assert); gotByThisMoment.AddRange(newTokens); fullList.AddRange(nextPart); } if (string.IsNullOrEmpty(offset)) { break; } } }
public AssertiveParser(AssertDelegate assertDelegate, Parser parser, string id, string message) { if (parser == null) { throw new ArgumentNullException("parser"); } if (id == null) { throw new ArgumentNullException("id"); } if (id == string.Empty) { throw new ArgumentException("id cannot be empty"); } Parser = parser; Message = message; ID = id; Assert = assertDelegate; }
public AssertiveParser( AssertDelegate assertDelegate, Parser parser, string id, string message) { if (parser == null) { throw new ArgumentNullException("parser"); } if (id == null) { throw new ArgumentNullException("id"); } if (id == string.Empty) { throw new ArgumentException("id cannot be empty"); } Parser = parser; Message = message; ID = id; Assert = assertDelegate; }
public static void ValidateNextPart(this BaseTest test, IEnumerable <string> gotByThisMoment, IEnumerable <string> newItems, string itemName, AssertDelegate assert) { List <string> newNotUnique = new List <string>(); // intersection within new part List <string> duplicated = new List <string>(); // intersection with received previously foreach (string token in newItems) { if (newItems.Count(S => S == token) > 1) { newNotUnique.Add(token); } if (gotByThisMoment.Count(S => S == token) > 0) { duplicated.Add(token); } } bool ok = true; StringBuilder error = new StringBuilder(); if (newNotUnique.Count > 0) { ok = false; error.AppendLine("The following tokens are not unique: " + string.Join(", ", newNotUnique.ToArray())); } if (duplicated.Count > 0) { ok = false; error.AppendLine("The following tokens have been already received: " + string.Join(", ", duplicated.ToArray())); } assert(ok, error.ToStringTrimNewLine(), "Validate response received", string.Empty); }
public static List <T> GetFullList <T>( GetListMethod <T> getList, int?chunk, string itemName, AssertDelegate assert) { List <T> fullList = new List <T>(); if (chunk > 0 || !chunk.HasValue) { string currentOffset = null; while (true) { T[] portion = null; currentOffset = getList(chunk, currentOffset, out portion); if (portion != null) { if (chunk.HasValue) { assert(portion.Length <= chunk, string.Format("{0} {1}s returned", portion.Length, itemName), "Check that MaxLimit parameter is not exceeded", string.Empty); } fullList.AddRange(portion); } if (string.IsNullOrEmpty(currentOffset)) { break; } } } return(fullList); }
/// <summary> /// Checks that list contains exactly one item with specified token /// </summary> /// <typeparam name="T">Item type</typeparam> /// <param name="test">Class containing test method in which validation should be performed.</param> /// <param name="list">Items list</param> /// <param name="token">Token of desired item</param> /// <param name="tokenSelector">Function to get token from Item</param> /// <param name="itemName">Name of item for eror description</param> /// <param name="assert"></param> public static void CheckRequestedInfo <T>(this BaseTest test, IEnumerable <T> list, string token, Func <T, string> tokenSelector, string itemName, AssertDelegate assert) { string error = string.Empty; int count = 0; if (list != null) { count = list.Count(); } if (count == 0) { error = string.Format("No {0} information returned", itemName); } else { if (count > 1) { error = "More than one entry returned"; } else { T item = list.First(); if (tokenSelector(item) != token) { error = "Entry for other token returned"; } } } assert(string.IsNullOrEmpty(error), error, "Check response", string.Empty); }
private void CompareReceivers(Receiver receiverFromList, Receiver receiverByToken, AssertDelegate assert) { bool ok = true; StringBuilder logger = new StringBuilder(); string token = receiverByToken.Token; if (receiverFromList.Token != receiverByToken.Token) { ok &= false; logger.Append(string.Format("Token of receiver in GetReceiverResponse is {0} " + "but in GetReceivesResponse is {1}{2}", receiverByToken.Token, receiverFromList.Token, Environment.NewLine)); } if (receiverFromList.Configuration.Mode != receiverByToken.Configuration.Mode) { ok &= false; logger.Append(string.Format("Mode of receiver in GetReceiverResponse is {0} " + "but in GetReceivesResponse is {1}{2}", receiverByToken.Configuration.Mode, receiverFromList.Configuration.Mode, Environment.NewLine)); } if (receiverFromList.Configuration.MediaUri != receiverByToken.Configuration.MediaUri) { ok &= false; logger.Append(string.Format("MediaUri of receiver in GetReceiverResponse is {0} " + "but in GetReceivesResponse is {1}{2}", receiverByToken.Configuration.MediaUri, receiverFromList.Configuration.MediaUri, Environment.NewLine)); } if (receiverFromList.Configuration.StreamSetup.Stream != receiverByToken.Configuration.StreamSetup.Stream) { ok &= false; logger.Append(string.Format("StreamSetup.Stream of receiver in GetReceiverResponse is {0} " + "but in GetReceivesResponse is {1}{2}", receiverByToken.Configuration.StreamSetup.Stream, receiverFromList.Configuration.StreamSetup.Stream, Environment.NewLine)); } string parameter = "Transport"; CompareTransports(receiverFromList.Configuration.StreamSetup.Transport, receiverByToken.Configuration.StreamSetup.Transport, logger, receiverByToken.Token, ref ok, parameter); assert(ok, logger.ToStringTrimNewLine(), string.Format("Compare receivers with token {0} in GetReceiversResponse and in GetReceiverResponse", token), null); }
public void GuardedAssert_ReturnsValueOfCalledFunction() { var ass = AssertDelegate.GuardedAssert(() => { return(false); }, () => true); Assert.IsFalse(ass()); }
public static void ValidateFullRecordingJobsList(GetRecordingJobsResponseItem[] jobs, GetRecordingsResponseItem[] recordings, AssertDelegate assert) { bool tokensOk = true; StringBuilder logger = new StringBuilder(); List <string> logged = new List <string>(); foreach (var item in jobs) { string token = item.JobConfiguration.RecordingToken; if (recordings.Where(r => r.RecordingToken == token).FirstOrDefault() == null) { tokensOk = false; logged.Add(token); logger.AppendFormat("Recording list doesn't contain recording {0} which token returned in GetRecordingJobsResponse", token, Environment.NewLine); } } assert(tokensOk, logger.ToStringTrimNewLine(), "Validate recording job list got from GetRecordingJobs", null); }
/// <summary> /// Wraps the Begin* part of a Begin / End method pair to allow for signaling when assertions have been violated. /// The instrumentation can be a performance hit, so this method should not be called if AppVerifier is not enabled. /// </summary> /// <param name="httpApplication">The HttpApplication instance for this request, used to get HttpContext and related items.</param> /// <param name="beginMethod">The Begin* part of a Begin / End method pair, likely wrapped in a lambda so only the AsyncCallback and object parameters are exposed.</param> /// <param name="originalDelegate">The original user-provided delegate, e.g. the thing that 'beginMethod' wraps. Provided so that we can show correct methods when asserting.</param> /// <param name="errorHandler">The listener that can handle verification failures.</param> /// <returns>The instrumented Begin* method.</returns> internal static Func <AsyncCallback, object, IAsyncResult> WrapBeginMethodImpl(HttpApplication httpApplication, Func <AsyncCallback, object, IAsyncResult> beginMethod, Delegate originalDelegate, Action <AppVerifierException> errorHandler, CallStackCollectionBitMasks callStackMask) { return((callback, state) => { // basic diagnostic info goes at the top since it's used during generation of the error message AsyncCallbackInvocationHelper asyncCallbackInvocationHelper = new AsyncCallbackInvocationHelper(); CallStackCollectionBitMasks myBeginMask = callStackMask & CallStackCollectionBitMasks.AllBeginMask; bool captureBeginStack = (myBeginMask & (CallStackCollectionBitMasks)AppVerifierCollectCallStackMask) == myBeginMask; InvocationInfo beginHandlerInvocationInfo = InvocationInfo.Capture(captureBeginStack); Uri requestUrl = null; RequestNotification?currentNotification = null; bool isPostNotification = false; Type httpHandlerType = null; // need to collect all this up-front since it might go away during the async operation if (httpApplication != null) { HttpContext context = httpApplication.Context; if (context != null) { if (!context.HideRequestResponse && context.Request != null) { requestUrl = context.Request.Unvalidated.Url; } if (context.NotificationContext != null) { currentNotification = context.NotificationContext.CurrentNotification; isPostNotification = context.NotificationContext.IsPostNotification; } if (context.Handler != null) { httpHandlerType = context.Handler.GetType(); } } } // If the condition passed to this method evaluates to false, we will raise an error to whoever is listening. AssertDelegate assert = (condition, errorCode) => { long mask = 1L << (int)errorCode; // assert only if it was not masked out by a bit set bool enableAssert = (AppVerifierErrorCodeEnableAssertMask & mask) == mask; if (!condition && enableAssert) { // capture the stack only if it was not masked out by a bit set bool captureStack = (AppVerifierErrorCodeCollectCallStackMask & mask) == mask; InvocationInfo assertInvocationInfo = InvocationInfo.Capture(captureStack); // header StringBuilder errorString = new StringBuilder(); errorString.AppendLine(FormatErrorString(SR.AppVerifier_Title)); errorString.AppendLine(FormatErrorString(SR.AppVerifier_Subtitle)); errorString.AppendLine(); // basic info (about the assert) errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_URL, requestUrl)); errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_ErrorCode, (int)errorCode)); errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_Description, GetLocalizedDescriptionStringForError(errorCode))); errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_ThreadInfo, assertInvocationInfo.ThreadId, assertInvocationInfo.Timestamp.ToLocalTime())); errorString.AppendLine(assertInvocationInfo.StackTrace.ToString()); // Begin* method info errorString.AppendLine(FormatErrorString(SR.AppVerifier_BeginMethodInfo_EntryMethod, PrettyPrintDelegate(originalDelegate))); if (currentNotification != null) { errorString.AppendLine(FormatErrorString(SR.AppVerifier_BeginMethodInfo_RequestNotification_Integrated, currentNotification, isPostNotification)); } else { errorString.AppendLine(FormatErrorString(SR.AppVerifier_BeginMethodInfo_RequestNotification_NotIntegrated)); } errorString.AppendLine(FormatErrorString(SR.AppVerifier_BeginMethodInfo_CurrentHandler, httpHandlerType)); errorString.AppendLine(FormatErrorString(SR.AppVerifier_BeginMethodInfo_ThreadInfo, beginHandlerInvocationInfo.ThreadId, beginHandlerInvocationInfo.Timestamp.ToLocalTime())); errorString.AppendLine(beginHandlerInvocationInfo.StackTrace.ToString()); // AsyncCallback info int totalAsyncInvocationCount; InvocationInfo firstAsyncInvocation = asyncCallbackInvocationHelper.GetFirstInvocationInfo(out totalAsyncInvocationCount); errorString.AppendLine(FormatErrorString(SR.AppVerifier_AsyncCallbackInfo_InvocationCount, totalAsyncInvocationCount)); if (firstAsyncInvocation != null) { errorString.AppendLine(FormatErrorString(SR.AppVerifier_AsyncCallbackInfo_FirstInvocation_ThreadInfo, firstAsyncInvocation.ThreadId, firstAsyncInvocation.Timestamp.ToLocalTime())); errorString.AppendLine(firstAsyncInvocation.StackTrace.ToString()); } AppVerifierException ex = new AppVerifierException(errorCode, errorString.ToString()); errorHandler(ex); throw ex; } }; assert(httpApplication != null, AppVerifierErrorCode.HttpApplicationInstanceWasNull); assert(originalDelegate != null, AppVerifierErrorCode.BeginHandlerDelegateWasNull); object lockObj = new object(); // used to synchronize access to certain locals which can be touched by multiple threads IAsyncResult asyncResultReturnedByBeginHandler = null; IAsyncResult asyncResultPassedToCallback = null; object beginHandlerReturnValueHolder = null; // used to hold the IAsyncResult returned by or Exception thrown by BeginHandler; see comments on Holder<T> for more info Thread threadWhichCalledBeginHandler = Thread.CurrentThread; // used to determine whether the callback was invoked synchronously bool callbackRanToCompletion = false; // don't need to lock when touching this local since it's only read in the synchronous case HttpContext assignedContextUponCallingBeginHandler = httpApplication.Context; // used to determine whether the underlying request disappeared try { asyncResultReturnedByBeginHandler = beginMethod( asyncResult => { try { CallStackCollectionBitMasks myCallbackMask = callStackMask & CallStackCollectionBitMasks.AllCallbackMask; bool captureEndCallStack = (myCallbackMask & AppVerifierCollectCallStackMask) == myCallbackMask; // The callback must never be called more than once. int newAsyncCallbackInvocationCount = asyncCallbackInvocationHelper.RecordInvocation(captureEndCallStack); assert(newAsyncCallbackInvocationCount == 1, AppVerifierErrorCode.AsyncCallbackInvokedMultipleTimes); // The 'asyncResult' parameter must never be null. assert(asyncResult != null, AppVerifierErrorCode.AsyncCallbackInvokedWithNullParameter); object tempBeginHandlerReturnValueHolder; Thread tempThreadWhichCalledBeginHandler; lock (lockObj) { asyncResultPassedToCallback = asyncResult; tempBeginHandlerReturnValueHolder = beginHandlerReturnValueHolder; tempThreadWhichCalledBeginHandler = threadWhichCalledBeginHandler; } // At this point, 'IsCompleted = true' is mandatory. assert(asyncResult.IsCompleted, AppVerifierErrorCode.AsyncCallbackGivenAsyncResultWhichWasNotCompleted); if (tempBeginHandlerReturnValueHolder == null) { // BeginHandler hasn't yet returned, so this call may be synchronous or asynchronous. // We can tell by comparing the current thread with the thread which called BeginHandler. // From a correctness perspective, it is valid to invoke the AsyncCallback delegate either // synchronously or asynchronously. From [....]: if 'CompletedSynchronously = true', then // AsyncCallback invocation can happen either on the same thread or on a different thread, // just as long as BeginHandler hasn't yet returned (which in true in this case). if (!asyncResult.CompletedSynchronously) { // If 'CompletedSynchronously = false', we must be on a different thread than the BeginHandler invocation. assert(tempThreadWhichCalledBeginHandler != Thread.CurrentThread, AppVerifierErrorCode.AsyncCallbackInvokedSynchronouslyButAsyncResultWasNotMarkedCompletedSynchronously); } } else { // BeginHandler already returned, so this invocation is definitely asynchronous. Holder <IAsyncResult> asyncResultHolder = tempBeginHandlerReturnValueHolder as Holder <IAsyncResult>; if (asyncResultHolder != null) { // We need to verify that the IAsyncResult we're given is the same that was returned by BeginHandler // and that the IAsyncResult is marked 'CompletedSynchronously = false'. assert(asyncResult == asyncResultHolder.Value, AppVerifierErrorCode.AsyncCallbackInvokedWithUnexpectedAsyncResultInstance); assert(!asyncResult.CompletedSynchronously, AppVerifierErrorCode.AsyncCallbackInvokedAsynchronouslyButAsyncResultWasMarkedCompletedSynchronously); } else { // If we reached this point, BeginHandler threw an exception. // The AsyncCallback should never be invoked if BeginHandler has already failed. assert(false, AppVerifierErrorCode.BeginHandlerThrewThenAsyncCallbackInvokedAsynchronously); } } // AsyncState must match the 'state' parameter passed to BeginHandler assert(asyncResult.AsyncState == state, AppVerifierErrorCode.AsyncCallbackInvokedWithUnexpectedAsyncResultAsyncState); // Make sure the underlying HttpApplication is still assigned to the captured HttpContext instance. // If not, this AsyncCallback invocation could end up completing *some other request's* operation, // resulting in data corruption. assert(assignedContextUponCallingBeginHandler == httpApplication.Context, AppVerifierErrorCode.AsyncCallbackCalledAfterHttpApplicationReassigned); } catch (AppVerifierException) { // We want to ---- any exceptions thrown by our verification logic, as the failure // has already been recorded by the appropriate listener. Just go straight to // invoking the callback. } // all checks complete - delegate control to the actual callback if (callback != null) { callback(asyncResult); } callbackRanToCompletion = true; }, state); // The return value must never be null. assert(asyncResultReturnedByBeginHandler != null, AppVerifierErrorCode.BeginHandlerReturnedNull); lock (lockObj) { beginHandlerReturnValueHolder = new Holder <IAsyncResult>(asyncResultReturnedByBeginHandler); } if (asyncResultReturnedByBeginHandler.CompletedSynchronously) { // If 'CompletedSynchronously = true', the IAsyncResult must be marked 'IsCompleted = true' // and the AsyncCallback must have been invoked synchronously (checked in the AsyncCallback verification logic). assert(asyncResultReturnedByBeginHandler.IsCompleted, AppVerifierErrorCode.BeginHandlerReturnedAsyncResultMarkedCompletedSynchronouslyButWhichWasNotCompleted); assert(asyncCallbackInvocationHelper.TotalInvocations != 0, AppVerifierErrorCode.BeginHandlerReturnedAsyncResultMarkedCompletedSynchronouslyButAsyncCallbackNeverCalled); } IAsyncResult tempAsyncResultPassedToCallback; lock (lockObj) { tempAsyncResultPassedToCallback = asyncResultPassedToCallback; } // The AsyncCallback may have been invoked (either synchronously or asynchronously). If it has been // invoked, we need to verify that it was given the same IAsyncResult returned by BeginHandler. // If the AsyncCallback hasn't yet been called, we skip this check, as the AsyncCallback verification // logic will eventually perform the check at the appropriate time. if (tempAsyncResultPassedToCallback != null) { assert(tempAsyncResultPassedToCallback == asyncResultReturnedByBeginHandler, AppVerifierErrorCode.BeginHandlerReturnedUnexpectedAsyncResultInstance); } // AsyncState must match the 'state' parameter passed to BeginHandler assert(asyncResultReturnedByBeginHandler.AsyncState == state, AppVerifierErrorCode.BeginHandlerReturnedUnexpectedAsyncResultAsyncState); // all checks complete return asyncResultReturnedByBeginHandler; } catch (AppVerifierException) { // We want to ---- any exceptions thrown by our verification logic, as the failure // has already been recorded by the appropriate listener. Just return the original // IAsyncResult so that the application continues to run. return asyncResultReturnedByBeginHandler; } catch (Exception ex) { if (asyncResultReturnedByBeginHandler == null) { // If we reached this point, an exception was thrown by BeginHandler, so we need to // record it and rethrow it. IAsyncResult tempAsyncResultPassedToCallback; lock (lockObj) { beginHandlerReturnValueHolder = new Holder <Exception>(ex); tempAsyncResultPassedToCallback = asyncResultPassedToCallback; } try { // The AsyncCallback should only be invoked if BeginHandler ran to completion. if (tempAsyncResultPassedToCallback != null) { // If AsyncCallback was invoked asynchronously, then by definition it was // scheduled prematurely since BeginHandler hadn't yet run to completion // (since whatever additional work it did after invoking the callback failed). // Therefore it is always wrong for BeginHandler to both throw and // asynchronously invoke AsyncCallback. assert(tempAsyncResultPassedToCallback.CompletedSynchronously, AppVerifierErrorCode.AsyncCallbackInvokedAsynchronouslyThenBeginHandlerThrew); // If AsyncCallback was invoked synchronously, then it must have been invoked // before BeginHandler surfaced the exception (since otherwise BeginHandler // wouldn't have reached the line of code that invoked AsyncCallback). But // AsyncCallback itself could have thrown, bubbling the exception up through // BeginHandler and back to us. If AsyncCallback ran to completion, then this // means BeginHandler did extra work (which failed) after invoking AsyncCallback, // so BeginHandler by definition hadn't yet run to completion. assert(!callbackRanToCompletion, AppVerifierErrorCode.AsyncCallbackInvokedSynchronouslyThenBeginHandlerThrew); } } catch (AppVerifierException) { // We want to ---- any exceptions thrown by our verification logic, as the failure // has already been recorded by the appropriate listener. Propagate the original // exception upward. } throw; } else { // We want to ---- any exceptions thrown by our verification logic, as the failure // has already been recorded by the appropriate listener. Just return the original // IAsyncResult so that the application continues to run. return asyncResultReturnedByBeginHandler; } } finally { // Since our local variables are GC-rooted in an anonymous object, we should // clear references to objects we no longer need so that the GC can reclaim // them if appropriate. lock (lockObj) { threadWhichCalledBeginHandler = null; } } }); }
public static void CommonGetListStartReferenceLimitTestBody <T>(this BaseTest test, Func <int> maxLimitSelector, GetListStepMethod <T> listSelector, Func <T, string> tokenSelector, Func <T, T, StringBuilder, bool> itemComparison, string itemName, RunStepDelegate runStepDelegate, AssertDelegate assert) { // Get maxLimit int maxLimit = maxLimitSelector(); Func <int, List <T> > getList = (limit) => { List <T> fullList = new List <T>(); List <string> gotByThisMoment = new List <string>(); string offset = null; while (true) { T[] nextPart = null; offset = listSelector(limit, offset, out nextPart, string.Format("Get {0} list with limit = {1} and start reference ='{2}'", itemName, limit, offset)); //assert(nextPart != null, string.Format("No {0}s returned", itemName), "Check that result is not null", string.Empty); int count = nextPart == null ? 0 : nextPart.Length; assert(count <= limit, string.Format("{0} {1}s returned when limit is {2}", count, itemName, limit), "Check that limit is not exceeded", string.Empty); if (count > 0) { List <string> newTokens = nextPart.Select(tokenSelector).ToList(); test.ValidateNextPart(gotByThisMoment, newTokens, itemName, assert); gotByThisMoment.AddRange(newTokens); fullList.AddRange(nextPart); } if (string.IsNullOrEmpty(offset)) { break; } } return(fullList); }; // get full list by maxLimit chunks List <T> gotByMaxLimit = getList(maxLimit); // get full list by 1 item List <T> gotByOne = getList(1); // check order // compare items //test.ValidateOrderedLists(gotByMaxLimit, gotByOne, itemName, tokenSelector, // string.Format("received with limit ={0}", maxLimit), "received with limit=1", // itemComparison, assert); if (maxLimit > 2) { int middle = maxLimit / 2 + 1; // 3=>2, 4=>3, 5=>3 List <T> gotByMiddle = getList(middle); // check order // compare items //test.ValidateOrderedLists(gotByOne, gotByMiddle, itemName, tokenSelector, // "received with limit=1", // string.Format("received with limit ={0}", middle), // itemComparison, assert); } }
public static void CommonGetListLimitTestBody <T>(this BaseTest test, Func <int> maxLimitSelector, Func <List <T> > fullListSelector, GetListStepMethod <T> listSelector, Func <T, string> tokenSelector, string itemName, AssertDelegate assert) { // Get max limit int maxLimit = maxLimitSelector(); // Get full list. Exit test, if no items of interest registered List <T> infos = fullListSelector(); if (infos == null || infos.Count == 0) { return; } test.ValidateTokensInList(infos, tokenSelector, assert); int count = infos.Count; // Get one item { T[] shortList = null; listSelector(1, null, out shortList, string.Format("Get {0} list with limit = 1", itemName)); assert(shortList != null, string.Format("No {0}s returned", itemName), "Check that result is not null", string.Empty); assert(shortList.Length <= 1, string.Format("{0} {1}s returned when limit is {2}", shortList.Length, itemName, 1), "Check that limit is not exceeded", string.Empty); } // maxLimit if (count > 1) { T[] actual = null; listSelector(maxLimit, null, out actual, string.Format("Get {0} list with limit = {1}", itemName, maxLimit)); assert(actual != null, string.Format("No {0}s returned", itemName), "Check that result is not null", string.Empty); assert(actual.Length <= maxLimit, string.Format("{0} {1}s returned when limit is {2}", actual.Length, itemName, maxLimit), "Check that limit is not exceeded", string.Empty); test.ValidateTokensInList(actual, tokenSelector, assert); } int cnt = Math.Min(count, maxLimit); int limit = cnt / 2 + 1; // 3 => 2, 4=> 3, 5=> 3, if (limit != maxLimit && limit != 1) { T[] infosArray = infos.ToArray(); System.Diagnostics.Debug.WriteLine(string.Format("Get {0} with limit = {1}", itemName, limit)); T[] expected = new T[limit]; Array.Copy(infosArray, 0, expected, 0, limit); T[] actual = null; listSelector(limit, null, out actual, string.Format("Get {0} list with limit = {1}", itemName, limit)); assert(actual != null, string.Format("No {0}s returned", itemName), "Check that result is not null", string.Empty); assert(actual.Length <= limit, string.Format("{0} {1}s returned when limit is {2}", actual.Length, itemName, limit), "Check that limit is not exceeded", string.Empty); test.ValidateTokensInList(actual, tokenSelector, assert); } }
public static void CommonGetListStartReferenceTestBody <T>(this BaseTest test, Func <int> maxLimitSelector, Func <int, List <T> > fullListSelector, Func <int?, int?, string, T[]> listSelector, Func <T, string> tokenSelector, Action <IEnumerable <T>, IEnumerable <T>, string, string> listComparisonAction, Func <T, T, StringBuilder, bool> itemComparison, string itemName, RunStepDelegate runStepDelegate, AssertDelegate assert) { int maxLimit = maxLimitSelector(); List <T> infos = fullListSelector(maxLimit); if (infos == null || infos.Count == 0) { return; } test.ValidateTokensInList(infos, tokenSelector, assert); int count = infos.Count; // one last item if (count > 1) { T[] shortList = listSelector(maxLimit, count - 1, string.Format("Get {0} list with offset = {1}", itemName, count - 1)); test.CheckRequestedInfo <T>(shortList, infos[count - 1], tokenSelector, itemComparison, itemName, assert); } // first "maxLimit" items { List <T> expected = infos.Take(maxLimit).ToList(); T[] actual = listSelector(maxLimit, 0, string.Format("Get {0} list with offset = 0", itemName)); test.ValidateTokensInList(actual, tokenSelector, assert); listComparisonAction(expected, actual, string.Format("of first {0} {1}", maxLimit, itemName), "received when passing offset=0"); } if (count > 2) { int offset = count / 2; // 3 => 1, 4 => 2, 5 => 2, 6 => 3 System.Diagnostics.Debug.WriteLine(string.Format("Get {0} with offset = {1}", itemName, offset)); // expected list T[] infosArray = infos.ToArray(); int cnt = Math.Min(maxLimit, count - offset); T[] expected = new T[cnt]; Array.Copy(infosArray, offset, expected, 0, cnt); T[] actual = listSelector(maxLimit, offset, string.Format("Get {0} list with offset = {1}", itemName, offset)); test.ValidateTokensInList(actual, tokenSelector, assert); test.ValidateSubset(actual, expected, itemName, tokenSelector, itemComparison, assert); } }
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="test"></param> /// <param name="list1"></param> /// <param name="list2"></param> /// <param name="itemName"></param> /// <param name="tokenSelector"></param> /// <param name="description1"></param> /// <param name="description2"></param> /// <param name="itemComparer"></param> /// <param name="assert"></param> public static void ValidateOrderedLists <T>(this BaseTest test, IList <T> list1, IList <T> list2, string itemName, Func <T, string> tokenSelector, string description1, string description2, Func <T, T, StringBuilder, bool> itemComparer, AssertDelegate assert) { bool ok = true; StringBuilder logger = new StringBuilder(); List <string> common = new List <string>(); /****************/ foreach (T info in list1) { string token = tokenSelector(info); T[] foundItems = list2.Where(I => tokenSelector(I) == token).ToArray(); if (foundItems.Length == 0) { logger.AppendFormat( "{0} with token '{1}' not found in list {2}{3}", itemName, tokenSelector(info), description2, Environment.NewLine); ok = false; } else { common.Add(token); } } foreach (T info in list2) { string token = tokenSelector(info); T[] foundItems = list1.Where(I => tokenSelector(I) == token).ToArray(); if (foundItems.Length == 0) { logger.AppendFormat( "{0} with token '{1}' not found in {2}{3}", itemName, tokenSelector(info), description1, Environment.NewLine); ok = false; } } /****************/ bool orderOk = true; // only if sets match if (ok) { for (int i = 0; i < list1.Count; i++) { string token1 = tokenSelector(list1[i]); string token2 = tokenSelector(list2[i]); if (token1 != token2) { orderOk = false; break; } } } if (!orderOk) { logger.AppendLine(string.Format("Order of {0} is different{1}", itemName, Environment.NewLine)); ok = false; } /****************/ // for common only if (itemComparer != null) { bool local = ArrayUtils.CompareListItems(list1, list2, tokenSelector, common, itemName, logger, itemComparer); ok = ok && local; } assert(ok, logger.ToStringTrimNewLine(), "Check that lists are the same", null); }
public static void CommonGetListByTokenListTestBody <T>(this BaseTest test, Func <int> maxLimitSelector, Func <List <T> > fullListSelector, Func <string[], T[]> listSelector, Func <T, string> tokenSelector, Action <IEnumerable <T>, IEnumerable <T>, string, string> listComparisonAction, string itemName, string itemInfoName, RunStepDelegate runStepDelegate, AssertDelegate assert) { List <T> infos = fullListSelector(); if (infos == null || infos.Count == 0) { return; } ValidateTokensInList(test, infos, tokenSelector, assert); // int maxLimit = maxLimitSelector(); List <string> tokens = new List <string>(); foreach (T info in infos) { tokens.Add(tokenSelector(info)); } List <T> expected = new List <T>(); List <string> tokensForSubsetTest = new List <string>(); // create list of randomly selected tokens. // create "expected" list { List <T> fullListCopy = new List <T>(infos); for (int i = 0; i < maxLimit; i++) { Random rnd = new Random(); int idx = rnd.Next(0, fullListCopy.Count - 1); tokensForSubsetTest.Add(tokenSelector(fullListCopy[idx])); expected.Add(fullListCopy[idx]); fullListCopy.RemoveAt(idx); if (fullListCopy.Count == 0) { break; } } } // test for random subset T[] actual = listSelector(tokensForSubsetTest.ToArray()); assert(actual != null && actual.Length > 0, "Empty list returned", "Check that the list is not empty", ""); ValidateTokensInList(test, actual, tokenSelector, assert); test.ValidateSubset(actual, expected, itemName, tokenSelector, null, assert); // Get by one foreach (string token in tokens) { T[] shortList = listSelector(new string[] { token }); CheckRequestedInfo(test, shortList, token, tokenSelector, itemName, assert); } }
/// <summary> /// Returns an Action that determines whether SynchronizationContext.Send or Post was called after the underlying request finished. /// The instrumentation can be a performance hit, so this method should not be called if AppVerifier is not enabled. /// </summary> /// <param name="syncContext">The ISyncContext (HttpApplication, WebSocketPipeline, etc.) on which to perform the check.</param> /// <param name="errorHandler">The listener that can handle verification failures.</param> /// <returns>A callback which performs the verification.</returns> internal static Action GetSyncContextCheckDelegateImpl(ISyncContext syncContext, Action <AppVerifierException> errorHandler) { Uri requestUrl = null; object originalThreadContextId = null; // collect all of the diagnostic information upfront HttpContext originalHttpContext = (syncContext != null) ? syncContext.HttpContext : null; if (originalHttpContext != null) { if (!originalHttpContext.HideRequestResponse && originalHttpContext.Request != null) { requestUrl = originalHttpContext.Request.Unvalidated.Url; } // This will be used as a surrogate for the captured HttpContext so that we don't // have a long-lived reference to a heavy object graph. See comments on ThreadContextId // for more info. originalThreadContextId = originalHttpContext.ThreadContextId; originalHttpContext = null; } // If the condition passed to this method evaluates to false, we will raise an error to whoever is listening. AssertDelegate assert = (condition, errorCode) => { long mask = 1L << (int)errorCode; // assert only if it was not masked out by a bit set bool enableAssert = (AppVerifierErrorCodeEnableAssertMask & mask) == mask; if (!condition && enableAssert) { // capture the stack only if it was not masked out by a bit set bool captureStack = (AppVerifierErrorCodeCollectCallStackMask & mask) == mask; InvocationInfo assertInvocationInfo = InvocationInfo.Capture(captureStack); // header StringBuilder errorString = new StringBuilder(); errorString.AppendLine(FormatErrorString(SR.AppVerifier_Title)); errorString.AppendLine(FormatErrorString(SR.AppVerifier_Subtitle)); errorString.AppendLine(); // basic info (about the assert) errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_URL, requestUrl)); errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_ErrorCode, (int)errorCode)); errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_Description, GetLocalizedDescriptionStringForError(errorCode))); errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_ThreadInfo, assertInvocationInfo.ThreadId, assertInvocationInfo.Timestamp.ToLocalTime())); errorString.AppendLine(assertInvocationInfo.StackTrace.ToString()); AppVerifierException ex = new AppVerifierException(errorCode, errorString.ToString()); errorHandler(ex); throw ex; } }; return(() => { try { // Make sure that the ISyncContext is still associated with the same HttpContext that // we captured earlier. HttpContext currentHttpContext = (syncContext != null) ? syncContext.HttpContext : null; object currentThreadContextId = (currentHttpContext != null) ? currentHttpContext.ThreadContextId : null; assert(currentThreadContextId != null && ReferenceEquals(originalThreadContextId, currentThreadContextId), AppVerifierErrorCode.SyncContextSendOrPostCalledAfterRequestCompleted); } catch (AppVerifierException) { // We want to ---- any exceptions thrown by our verification logic, as the failure // has already been recorded by the appropriate listener. Propagate the original // exception upward. } }); }