private static IExportProviderFactory CreateRemoteHostExportProviderFactory()
        {
            var configuration      = CompositionConfiguration.Create(ExportProviderCache.GetOrCreateAssemblyCatalog(RoslynServices.RemoteHostAssemblies).WithCompositionService());
            var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration);

            return(runtimeComposition.CreateExportProviderFactory());
        }
Example #2
0
        private IExportProviderFactory GetOrCreateFactory()
        {
            var key = new CacheKey(Assemblies, Parts, ExcludedPartTypes);

            lock (s_factoryCache)
            {
                if (s_factoryCache.TryGetValue(key, out var existing))
                {
                    return(existing);
                }
            }

            var newFactory = ExportProviderCache.CreateExportProviderFactory(GetCatalog(), IsRemote);

            lock (s_factoryCache)
            {
                if (s_factoryCache.TryGetValue(key, out var existing))
                {
                    return(existing);
                }

                s_factoryCache.Add(key, newFactory);
            }

            return(newFactory);
        }
        private MefHostServices CreateMefHostServices(IEnumerable <Assembly> assemblies)
        {
            ExportProvider exportProvider;

            if (assemblies is ImmutableArray <Assembly> array &&
                array == MefHostServices.DefaultAssemblies &&
                ExportProviderCache.LocalExportProviderForCleanup != null)
            {
                if (_hostServices != null)
                {
                    return(_hostServices);
                }

                exportProvider = ExportProviderCache.LocalExportProviderForCleanup;
            }
            else
            {
                exportProvider = ExportProviderCache.GetOrCreateExportProviderFactory(assemblies).CreateExportProvider();
            }

            Interlocked.CompareExchange(
                ref _hostServices,
                new ExportProviderMefHostServices(exportProvider),
                null);

            return(_hostServices);
        }
Example #4
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);
        }
Example #6
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);
            }
        }
        private MefHostServices CreateMefHostServices(IEnumerable <Assembly> assemblies, bool requestingDefaultAssemblies)
        {
            if (requestingDefaultAssemblies && ExportProviderCache.ExportProviderForCleanup != null)
            {
                if (_hostServices == null)
                {
                    var hostServices = new ExportProviderMefHostServices(ExportProviderCache.ExportProviderForCleanup);
                    Interlocked.CompareExchange(ref _hostServices, hostServices, null);
                }

                return(_hostServices);
            }

            var catalog = ExportProviderCache.GetOrCreateAssemblyCatalog(assemblies);

            Interlocked.CompareExchange(
                ref _hostServices,
                new ExportProviderMefHostServices(ExportProviderCache.GetOrCreateExportProviderFactory(catalog).CreateExportProvider()),
                null);

            return(_hostServices);
        }
Example #9
0
 private ComposableCatalog GetCatalog()
 => ExportProviderCache.CreateAssemblyCatalog(Assemblies, ExportProviderCache.CreateResolver()).WithoutPartsOfTypes(ExcludedPartTypes).WithParts(Parts);
        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);
            }
        }