Exemple #1
0
        /// <summary>
        /// To the extent reasonably possible, this method resets the state of the test environment to the same state as
        /// it started, ensuring that tests running in sequence cannot influence the outcome of later tests.
        /// </summary>
        /// <remarks>
        /// <para>The test cleanup runs in two primary steps:</para>
        /// <list type="number">
        /// <item>Waiting for asynchronous operations started by the test to complete.</item>
        /// <item>Disposing of mutable resources created by the test.</item>
        /// <item>Clearing static state variables related to the use of MEF during a test.</item>
        /// </list>
        /// </remarks>
        public override void After(MethodInfo methodUnderTest)
        {
            var exportProvider = ExportProviderCache.ExportProviderForCleanup;

            try
            {
                var listenerProvider = exportProvider?.GetExportedValues <IAsynchronousOperationListenerProvider>().SingleOrDefault();
                if (listenerProvider != null)
                {
                    if (ForegroundThreadAffinitizedObject.CurrentForegroundThreadData.Kind != ForegroundThreadDataKind.Unknown)
                    {
                        // Immediately clear items from the foreground notification service for which cancellation is
                        // requested. This service maintains a queue separately from Tasks, and work items scheduled for
                        // execution after a delay are not immediately purged when cancellation is requested. This code
                        // instructs the service to walk the list of queued work items and immediately cancel and purge any
                        // which are already cancelled.
                        var foregroundNotificationService = exportProvider?.GetExportedValues <IForegroundNotificationService>().SingleOrDefault() as ForegroundNotificationService;
                        foregroundNotificationService?.ReleaseCancelledItems();
                    }

                    // Join remaining operations with a timeout
                    using (var timeoutTokenSource = new CancellationTokenSource(CleanupTimeout))
                    {
                        try
                        {
                            var waiter = ((AsynchronousOperationListenerProvider)listenerProvider).WaitAllDispatcherOperationAndTasksAsync();
                            waiter.JoinUsingDispatcher(timeoutTokenSource.Token);
                        }
                        catch (OperationCanceledException ex) when(timeoutTokenSource.IsCancellationRequested)
                        {
                            var messageBuilder = new StringBuilder("Failed to clean up listeners in a timely manner.");

                            foreach (var token in ((AsynchronousOperationListenerProvider)listenerProvider).GetTokens())
                            {
                                messageBuilder.AppendLine().Append($"  {token}");
                            }

                            throw new TimeoutException(messageBuilder.ToString(), ex);
                        }
                    }
                }
            }
            finally
            {
                // Dispose of the export provider, including calling Dispose for any IDisposable services created during
                // the test.
                exportProvider?.Dispose();

                // Replace hooks with ones that always throw exceptions. These hooks detect cases where code executing
                // after the end of a test attempts to create an ExportProvider.
                MefHostServices.HookServiceCreation(DenyMefHostServicesCreationBetweenTests);
                RoslynServices.HookHostServices(() => throw new InvalidOperationException("Cannot create host services after test tear down."));

                // Reset static state variables.
                DesktopMefHostServices.ResetHostServicesTestOnly();
                _hostServices = null;
                ExportProviderCache.SetEnabled_OnlyUseExportProviderAttributeCanCall(false);
            }
        }
        public override void Before(MethodInfo methodUnderTest)
        {
            MefHostServices.TestAccessor.HookServiceCreation(CreateMefHostServices);

            // make sure we enable this for all unit tests
            AsynchronousOperationListenerProvider.Enable(enable: true, diagnostics: true);
            ExportProviderCache.SetEnabled_OnlyUseExportProviderAttributeCanCall(true);
        }
Exemple #3
0
        public override void Before(MethodInfo methodUnderTest)
        {
            MefHostServices.HookServiceCreation(CreateMefHostServices);
            RoslynServices.HookHostServices(() => _remoteHostServices.Value);
            DesktopMefHostServices.ResetHostServicesTestOnly();

            // make sure we enable this for all unit tests
            AsynchronousOperationListenerProvider.Enable(enable: true, diagnostics: true);
            ExportProviderCache.SetEnabled_OnlyUseExportProviderAttributeCanCall(true);
        }
        /// <summary>
        /// To the extent reasonably possible, this method resets the state of the test environment to the same state as
        /// it started, ensuring that tests running in sequence cannot influence the outcome of later tests.
        /// </summary>
        /// <remarks>
        /// <para>The test cleanup runs in two primary steps:</para>
        /// <list type="number">
        /// <item>Waiting for asynchronous operations started by the test to complete.</item>
        /// <item>Disposing of mutable resources created by the test.</item>
        /// <item>Clearing static state variables related to the use of MEF during a test.</item>
        /// </list>
        /// </remarks>
        public override void After(MethodInfo methodUnderTest)
        {
            try
            {
                DisposeExportProvider(ExportProviderCache.LocalExportProviderForCleanup);
                DisposeExportProvider(ExportProviderCache.RemoteExportProviderForCleanup);
            }
            finally
            {
                // Replace hooks with ones that always throw exceptions. These hooks detect cases where code executing
                // after the end of a test attempts to create an ExportProvider.
                MefHostServices.TestAccessor.HookServiceCreation(DenyMefHostServicesCreationBetweenTests);

                // Reset static state variables.
                _hostServices = null;
                ExportProviderCache.SetEnabled_OnlyUseExportProviderAttributeCanCall(false);
            }
        }
        public override void After(MethodInfo methodUnderTest)
        {
            var exportProvider = ExportProviderCache.ExportProviderForCleanup;

            try
            {
                if (exportProvider?.GetExportedValues <IAsynchronousOperationListenerProvider>().SingleOrDefault() is { } listenerProvider)
                {
                    if (exportProvider.GetExportedValues <IThreadingContext>().SingleOrDefault()?.HasMainThread ?? false)
                    {
                        // Immediately clear items from the foreground notification service for which cancellation is
                        // requested. This service maintains a queue separately from Tasks, and work items scheduled for
                        // execution after a delay are not immediately purged when cancellation is requested. This code
                        // instructs the service to walk the list of queued work items and immediately cancel and purge any
                        // which are already cancelled.
                        var foregroundNotificationService = exportProvider.GetExportedValues <IForegroundNotificationService>().SingleOrDefault() as ForegroundNotificationService;
                        foregroundNotificationService?.ReleaseCancelledItems();
                    }

                    // Join remaining operations with a timeout
                    using (var timeoutTokenSource = new CancellationTokenSource(CleanupTimeout))
                    {
                        try
                        {
                            var waiter = ((AsynchronousOperationListenerProvider)listenerProvider).WaitAllDispatcherOperationAndTasksAsync();
                            waiter.JoinUsingDispatcher(timeoutTokenSource.Token);
                        }
                        catch (OperationCanceledException ex) when(timeoutTokenSource.IsCancellationRequested)
                        {
                            var messageBuilder = new StringBuilder("Failed to clean up listeners in a timely manner.");

                            foreach (var token in ((AsynchronousOperationListenerProvider)listenerProvider).GetTokens())
                            {
                                messageBuilder.AppendLine().Append($"  {token}");
                            }

                            throw new TimeoutException(messageBuilder.ToString(), ex);
                        }
                    }

                    // Verify the synchronization context was not used incorrectly
                    var testExportJoinableTaskContext = exportProvider.GetExportedValues <TestExportJoinableTaskContext>().SingleOrDefault();
                    if (testExportJoinableTaskContext?.SynchronizationContext is TestExportJoinableTaskContext.DenyExecutionSynchronizationContext synchronizationContext)
                    {
                        synchronizationContext.ThrowIfSwitchOccurred();
                    }

                    foreach (var testErrorHandler in exportProvider.GetExportedValues <ITestErrorHandler>())
                    {
                        var exceptions = testErrorHandler.Exceptions;
                        if (exceptions.Count > 0)
                        {
                            throw new AggregateException("Tests threw unexpected exceptions", exceptions);
                        }
                    }
                }
            }
            finally
            {
                // Dispose of the export provider, including calling Dispose for any IDisposable services created during
                // the test.
                exportProvider?.Dispose();

                // Replace hooks with ones that always throw exceptions. These hooks detect cases where code executing
                // after the end of a test attempts to create an ExportProvider.
                MefHostServices.TestAccessor.HookServiceCreation(DenyMefHostServicesCreationBetweenTests);
                RoslynServices.TestAccessor.HookHostServices(() => throw new InvalidOperationException("Cannot create host services after test tear down."));

                // Reset static state variables.
                _hostServices = null;
                ExportProviderCache.SetEnabled_OnlyUseExportProviderAttributeCanCall(false);
            }
        }