private TestFrameworkSelection GetFallbackSelection(
            Dictionary <object, TestFrameworkSelection> selections,
            IList <AssemblyName> assemblyReferences,
            IEnumerable <ComponentHandle <ITestFramework, TestFrameworkTraits> > filteredTestFrameworkHandlesWithoutFallback,
            TestFrameworkOptions testFrameworkOptions,
            TestFrameworkFallbackMode testFrameworkFallbackMode)
        {
            // Strict fallback mode.
            if (testFrameworkFallbackMode == TestFrameworkFallbackMode.Strict)
            {
                return(null);
            }

            // Approximate fallback mode.
            if (assemblyReferences != null)
            {
                HashSet <string> matchingReferences = null;
                HashSet <string> matchingSignatures = null;

                foreach (var testFrameworkHandle in filteredTestFrameworkHandlesWithoutFallback)
                {
                    IList <AssemblySignature> assemblySignatures = testFrameworkHandle.GetTraits().FrameworkAssemblies;

                    foreach (AssemblyName assemblyName in assemblyReferences)
                    {
                        foreach (AssemblySignature assemblySignature in assemblySignatures)
                        {
                            if (assemblySignature.Name == assemblyName.Name)
                            {
                                if (matchingReferences == null)
                                {
                                    matchingReferences = new HashSet <string>();
                                    matchingSignatures = new HashSet <string>();
                                }

                                matchingReferences.Add(assemblyName.FullName);
                                matchingSignatures.Add(assemblySignature.ToString());
                            }
                        }
                    }
                }

                if (matchingReferences != null)
                {
                    StringBuilder fallbackExplanationBuilder = new StringBuilder();

                    fallbackExplanationBuilder.Append("Detected a probable test framework assembly version mismatch.\n");

                    fallbackExplanationBuilder.Append("Referenced test frameworks: ");
                    AppendQuotedItems(fallbackExplanationBuilder, matchingReferences);
                    fallbackExplanationBuilder.Append(".\n");

                    fallbackExplanationBuilder.Append("Supported test frameworks: ");
                    AppendQuotedItems(fallbackExplanationBuilder, matchingSignatures);
                    fallbackExplanationBuilder.Append(".");

                    string fallbackExplanation = fallbackExplanationBuilder.ToString();
                    return(GetOrCreateSelectionIfAbsent(selections, fallbackExplanation, () =>
                    {
                        TestFrameworkOptions fallbackTestFrameworkOptions = testFrameworkOptions.Copy();
                        fallbackTestFrameworkOptions.AddProperty(FallbackTestFramework.FallbackExplanationKey,
                                                                 fallbackExplanation);
                        return new TestFrameworkSelection(fallbackTestFrameworkHandle, fallbackTestFrameworkOptions,
                                                          true);
                    }));
                }
            }

            if (testFrameworkFallbackMode == TestFrameworkFallbackMode.Approximate)
            {
                return(null);
            }

            // Default fallback mode.
            return(GetOrCreateSelectionIfAbsent(selections, DefaultFallbackSelectionKey,
                                                () => new TestFrameworkSelection(fallbackTestFrameworkHandle, testFrameworkOptions, true)));
        }
 public TestDriverData(TestFrameworkOptions testFrameworkOptions)
 {
     TestFrameworkHandles = new List <ComponentHandle <ITestFramework, TestFrameworkTraits> >();
     TestFrameworkOptions = testFrameworkOptions;
     Items = new List <T>();
 }
        SelectTestFrameworksForFilesImpl(
            IEnumerable <ComponentHandle <ITestFramework, TestFrameworkTraits> > filteredTestFrameworkHandlesWithoutFallback,
            TestFrameworkFallbackMode testFrameworkFallbackMode,
            TestFrameworkOptions testFrameworkOptions,
            IEnumerable <FileInfo> files)
        {
            var selections = new Dictionary <object, TestFrameworkSelection>();
            var partitions = new MultiMap <TestFrameworkSelection, FileInfo>();

            foreach (var file in files)
            {
                try
                {
                    bool supported = false;
                    IList <AssemblyName> assemblyReferences = null;
                    using (var fileInspector = new LazyFileInspector(file))
                    {
                        FileType fileType = fileTypeManager.IdentifyFileType(fileInspector);

                        foreach (var testFrameworkHandle in filteredTestFrameworkHandlesWithoutFallback)
                        {
                            TestFrameworkTraits traits = testFrameworkHandle.GetTraits();
                            if (!traits.IsFrameworkCompatibleWithFileType(fileType, fileTypeManager))
                            {
                                continue;
                            }

                            // If the file is an assembly, then filter further by assembly references.
                            if (fileType.IsSameOrSubtypeOf(fileTypeManager.GetFileTypeById("Assembly")))
                            {
                                if (assemblyReferences == null)
                                {
                                    assemblyReferences = GetAssemblyReferences(fileInspector);
                                }

                                if (!traits.IsFrameworkCompatibleWithAssemblyReferences(assemblyReferences))
                                {
                                    continue;
                                }
                            }

                            TestFrameworkSelection selection = GetOrCreateSelectionIfAbsent(
                                selections, testFrameworkHandle,
                                () => new TestFrameworkSelection(testFrameworkHandle, testFrameworkOptions, false));

                            partitions.Add(selection, file);
                            supported = true;
                        }
                    }

                    if (!supported)
                    {
                        TestFrameworkSelection selection = GetFallbackSelection(selections, assemblyReferences,
                                                                                filteredTestFrameworkHandlesWithoutFallback, testFrameworkOptions, testFrameworkFallbackMode);
                        if (selection != null)
                        {
                            partitions.Add(selection, file);
                        }
                    }
                }
                catch (IOException exception)
                {
                    logger.Log(LogSeverity.Error, string.Format("Skipping file '{0}' due to IO error.", file.FullName), exception);
                }
                catch (UnauthorizedAccessException exception)
                {
                    logger.Log(LogSeverity.Error, string.Format("Skipping file '{0}' due to security error", file.FullName), exception);
                }
            }

            return(partitions);
        }