コード例 #1
0
ファイル: PluginManager.cs プロジェクト: ZHJEE/OpenTAP
 /// <summary>
 /// Start a search task that finds plugins to the platform.
 /// This call is not blocking, some other calls to PluginManager will automatically
 /// wait for this task to finish (or even start it if it hasn't been already). These calls
 /// include <see cref="GetAllPlugins"/>, <see cref="GetPlugins{BaseType}"/>,
 /// <see cref="GetPlugins(Type)"/>, <see cref="LocateType(string)"/> and <see cref="LocateTypeData(string)"/>
 /// </summary>
 public static Task SearchAsync()
 {
     searchTask.Reset();
     searcher = null;
     ChangeID++;
     TapThread.Start(Search);
     return(Task.Run(() => GetSearcher()));
 }
コード例 #2
0
ファイル: PluginManager.cs プロジェクト: ZHJEE/OpenTAP
        /// <summary>
        /// Gets all plugins. I.e. all types that descend from <see cref="ITapPlugin"/>.
        /// Abstract types and interfaces are not included.
        /// This does not require/cause the assembly containing the type to be loaded.
        /// This will search for plugins if not done already (i.e. call and wait for <see cref="PluginManager.SearchAsync()"/>)
        /// Only C#/.NET types are returned. To also get dynamic types (from custom <see cref="ITypeDataSearcher"/>s) use <see cref="TypeData.GetDerivedTypes(ITypeData)"/> instead.
        /// </summary>
        public static ReadOnlyCollection <TypeData> GetAllPlugins()
        {
            PluginSearcher searcher = GetSearcher();

            return(searcher.PluginTypes
                   .Where(st => !st.TypeAttributes.HasFlag(TypeAttributes.Interface) && !st.TypeAttributes.HasFlag(TypeAttributes.Abstract))
                   .ToList().AsReadOnly());
        }
コード例 #3
0
ファイル: PackageDefTests.cs プロジェクト: ZHJEE/OpenTAP
        public void CreatePackageDepVersions()
        {
            var tmp  = Path.GetTempFileName();
            var tmp2 = Path.GetTempFileName();

            Directory.Move("Packages", "Packages2");
            try
            {
                {
                    PackageDef def = new PackageDef();
                    def.Name     = "test";
                    def.InfoLink = "a";
                    def.Date     = DateTime.Today;

                    def.AddFile(tmp);

                    var bs = PluginManager.GetSearcher().Assemblies.First(asm => asm.Name == "OpenTap.Plugins.BasicSteps");
                    def.Files[0].DependentAssemblies.Add(bs);

                    var searcher = new PluginSearcher();
                    searcher.Search(Directory.GetCurrentDirectory());
                    List <AssemblyData> assemblies = searcher.Assemblies.ToList();
                    def.findDependencies(new List <string>(), assemblies);

                    Assert.AreEqual(0, def.Dependencies.Count);
                    Assert.AreNotEqual(0, def.Files.Count);
                }

                {
                    PackageDef def = new PackageDef();

                    def.AddFile(tmp);

                    var bs = PluginManager.GetSearcher().Assemblies.First(asm => asm.Name == "OpenTap.Plugins.BasicSteps");
                    def.Files[0].DependentAssemblies.Add(bs);

                    var searcher = new PluginSearcher();
                    searcher.Search(Directory.GetCurrentDirectory());
                    List <AssemblyData> assemblies = searcher.Assemblies.ToList();
                    def.findDependencies(new List <string> {
                        "OpenTap"
                    }, assemblies);

                    Assert.AreEqual(0, def.Dependencies.Count);
                    Assert.AreNotEqual(1, def.Files.Count);
                }
            }
            finally
            {
                if (Directory.Exists("Packages"))
                {
                    Directory.Delete("Packages", true);
                }
                Directory.Move("Packages2", "Packages");
            }
        }
コード例 #4
0
ファイル: PluginSearcherTests.cs プロジェクト: ZHJEE/OpenTAP
        public void SameAssemblyTwice()
        {
            PluginSearcher searcher = new PluginSearcher();

            try
            {
                Directory.CreateDirectory("SameAssemblyTwiceTestDir");
                File.Copy("OpenTap.UnitTests.dll", "SameAssemblyTwiceTestDir/OpenTap.UnitTests.dll", true);
                searcher.Search(new string[] { "OpenTap.UnitTests.dll", "OpenTap.dll", "SameAssemblyTwiceTestDir/OpenTap.UnitTests.dll" });
                Assert.AreEqual(2, searcher.Assemblies.Count());
            }
            finally
            {
                Directory.Delete("SameAssemblyTwiceTestDir", true);
            }
        }
コード例 #5
0
ファイル: PluginManager.cs プロジェクト: ZHJEE/OpenTAP
        /// <summary>
        /// Searches the files in fileNames for dlls implementing <see cref="ITapPlugin"/>
        /// and puts the implementation in the appropriate list.
        /// </summary>
        /// <param name="_fileNames">List of files to search.</param>
        static PluginSearcher SearchAndAddToStore(IEnumerable <string> _fileNames)
        {
            var            fileNames = _fileNames.ToList();
            Stopwatch      timer     = Stopwatch.StartNew();
            PluginSearcher searcher  = new PluginSearcher();

            try
            {
                var w2 = Stopwatch.StartNew();
                IEnumerable <TypeData>     foundPluginTypes = searcher.Search(fileNames);
                IEnumerable <AssemblyData> foundAssemblies  = foundPluginTypes.Select(p => p.Assembly).Distinct();
                log.Debug(w2, "Found {0} plugin assemblies containing {1} plugin types.", foundAssemblies.Count(), foundPluginTypes.Count());

                foreach (AssemblyData asm in foundAssemblies)
                {
                    assemblyResolver.AddAssembly(asm.Name, asm.Location);

                    if (asm.Location.Contains(AppDomain.CurrentDomain.BaseDirectory))
                    {
                        log.Debug("Found version {0,-16} of {1}", asm.SemanticVersion?.ToString() ?? asm.Version?.ToString(), Path.GetFileName(asm.Location));
                    }
                    else
                    {
                        // log full path of assembly if it was loaded with --search from another directory.
                        log.Debug("Found version {0,-16} of {1} from {2}", asm.SemanticVersion?.ToString() ?? asm.Version?.ToString(), Path.GetFileName(asm.Location), asm.Location);
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("Plugin search failed for: " + String.Join(", ", fileNames));
                log.Debug(ex);
            }
            log.Debug(timer, "Searched {0} Assemblies.", fileNames.Count);


            if (GetPlugins(searcher, typeof(IInstrument).FullName).Count == 0)
            {
                log.Warning("No instruments found.");
            }
            if (GetPlugins(searcher, typeof(ITestStep).FullName).Count == 0)
            {
                log.Warning("No TestSteps found.");
            }
            return(searcher);
        }
コード例 #6
0
        public static SemanticVersion GetVersion(string path)
        {
            var searcher = new PluginSearcher();

            searcher.Search(new[] { path });

            var asm = searcher.Assemblies.First();

            using (FileStream file = new FileStream(asm.Location, FileMode.Open, FileAccess.Read))
                using (PEReader header = new PEReader(file, PEStreamOptions.LeaveOpen))
                {
                    var CurrentReader = header.GetMetadataReader();

                    foreach (CustomAttributeHandle attrHandle in CurrentReader.GetAssemblyDefinition().GetCustomAttributes())
                    {
                        CustomAttribute attr = CurrentReader.GetCustomAttribute(attrHandle);
                        if (attr.Constructor.Kind == HandleKind.MemberReference)
                        {
                            var    ctor = CurrentReader.GetMemberReference((MemberReferenceHandle)attr.Constructor);
                            string attributeFullName = "";
                            if (ctor.Parent.Kind == HandleKind.TypeDefinition)
                            {
                                var def = CurrentReader.GetTypeDefinition((TypeDefinitionHandle)ctor.Parent);
                                attributeFullName = string.Format("{0}.{1}", CurrentReader.GetString(def.Namespace), CurrentReader.GetString(def.Name));
                            }
                            if (ctor.Parent.Kind == HandleKind.TypeReference)
                            {
                                var r = CurrentReader.GetTypeReference((TypeReferenceHandle)ctor.Parent);
                                attributeFullName = string.Format("{0}.{1}", CurrentReader.GetString(r.Namespace), CurrentReader.GetString(r.Name));
                            }

                            if (attributeFullName == typeof(System.Reflection.AssemblyInformationalVersionAttribute).FullName)
                            {
                                var valueString = attr.DecodeValue(new CustomAttributeTypeProvider());
                                if (SemanticVersion.TryParse(valueString.FixedArguments[0].Value.ToString(), out SemanticVersion infoVer))
                                {
                                    return(infoVer);
                                }
                            }
                        }
                    }
                }

            return(null);
        }
コード例 #7
0
ファイル: PluginSearcherTests.cs プロジェクト: ZHJEE/OpenTAP
        public void PluginSearcherBasics()
        {
            PluginSearcher searcher = new PluginSearcher();

            searcher.Search(new string[] { "OpenTap.UnitTests.dll", "OpenTap.dll" });
            CollectionAssert.AllItemsAreInstancesOfType(searcher.PluginTypes.ToList(), typeof(TypeData));
            CollectionAssert.AllItemsAreNotNull(searcher.PluginTypes.ToList());
            CollectionAssert.AllItemsAreUnique(searcher.PluginTypes.ToList());

            var instrType = searcher.PluginTypes.FirstOrDefault(st => st.Name == "OpenTap.IInstrument");

            Assert.IsNotNull(instrType);
            // Test of SearchType.PluginTypes (should be the type itself, as this is IInstrument is a plugin type - it directly implements ITapPlugin)
            Assert.AreEqual(instrType, instrType.PluginTypes.First());
            // Test of SearchType.Display
            Assert.IsNotNull(instrType.Display);
            Assert.AreEqual("Instrument", instrType.Display.Name);
            // Test of SearchType.Assembly
            Assert.AreEqual("OpenTap", instrType.Assembly.Name);

            var instrImplType = searcher.PluginTypes.FirstOrDefault(st => st.Name == "OpenTap.Engine.UnitTests.InstrumentTest");

            Assert.IsNotNull(instrImplType);
            // Test of SearchType.PluginTypes
            Assert.AreEqual(1, instrImplType.PluginTypes.Count());
            Assert.AreEqual(instrType, instrImplType.PluginTypes.First());
            // Test of SearchType.DerivedTypes
            CollectionAssert.Contains(instrType.DerivedTypes.ToArray(), instrImplType);
            // Test of SearchAssembly.References
            CollectionAssert.Contains(instrImplType.Assembly.References.ToList(), instrType.Assembly);
            // Test of SearchAssembly.Load()
            Assert.AreEqual(Assembly.GetExecutingAssembly(), instrImplType.Assembly.Load());
            // Test of SearchType.Load()
            Assert.AreEqual(typeof(OpenTap.Engine.UnitTests.InstrumentTest), instrImplType.Load());

            // Test of nested class
            var stepType = searcher.PluginTypes.FirstOrDefault(st => st.Name == "OpenTap.Engine.UnitTests.TestPlanTestFixture1+TestPlanTestStep");

            Assert.IsNotNull(stepType);

            CollectionAssert.IsSubsetOf(searcher.PluginTypes.ToList(), searcher.AllTypes.Values);
        }
コード例 #8
0
ファイル: PluginManager.cs プロジェクト: ZHJEE/OpenTAP
            static ReadOnlyCollection <Type> getPlugins(Type pluginBaseType)
            {
                if (pluginBaseType == null)
                {
                    throw new ArgumentNullException("pluginBaseType");
                }


                PluginSearcher searcher        = GetSearcher(); // Wait for the search to complete (and get the result)
                var            unloadedPlugins = PluginManager.GetPlugins(searcher, pluginBaseType.FullName);

                if (unloadedPlugins.Count == 0)
                {
                    return(emptyTypes);
                }

                int notLoadedTypesCnt = unloadedPlugins.Count(pl => pl.Status == LoadStatus.NotLoaded);

                if (notLoadedTypesCnt > 0)
                {
                    var notLoadedAssembliesCnt = unloadedPlugins.Select(x => x.Assembly).Distinct().Where(asm => asm.Status == LoadStatus.NotLoaded).ToArray();
                    if (notLoadedAssembliesCnt.Length > 0)
                    {
                        notLoadedAssembliesCnt.AsParallel().ForAll(asm => asm.Load());
                    }
                }
                IEnumerable <TypeData> plugins = unloadedPlugins;

                if (notLoadedTypesCnt > 8)
                {
                    // only find types in parallel if there are sufficiently many.
                    plugins = plugins
                              .AsParallel() // This is around 50% faster when many plugins are loaded in parallel.
                              .AsOrdered(); // ensure the order is the same as before.
                }

                return(plugins
                       .Select(td => td.Load())
                       .Where(x => x != null)
                       .ToList()
                       .AsReadOnly());
            }
コード例 #9
0
ファイル: PluginManager.cs プロジェクト: ZHJEE/OpenTAP
        private static Type locateType(string typeName)
        {
            PluginSearcher searcher = GetSearcher();

            if (string.IsNullOrWhiteSpace(typeName))
            {
                return(null);
            }
            if ((typeName.Length > 2) && (typeName[typeName.Length - 2] == '[') && (typeName[typeName.Length - 1] == ']'))
            {
                var elemType = LocateType(typeName.Substring(0, typeName.Length - 2));
                if (elemType != null)
                {
                    return(elemType.MakeArrayType());
                }
                else
                {
                    return(null);
                }
            }
            else if (searcher.AllTypes.ContainsKey(typeName))
            {
                TypeData t      = searcher.AllTypes[typeName];
                var      loaded = t.Load();
                if (loaded != null)
                {
                    return(loaded);
                }
            }

            if (typeName.Contains(","))
            {
                var x = locateType(typeName.Split(',')[0]);
                if (x != null)
                {
                    return(x);
                }
            }

            return(Type.GetType(typeName));
        }
コード例 #10
0
ファイル: PluginManager.cs プロジェクト: ZHJEE/OpenTAP
 ///<summary>Searches for plugins.</summary>
 public static void Search()
 {
     searchTask.Reset();
     searcher = null;
     assemblyResolver.Invalidate(DirectoriesToSearch);
     ChangeID++;
     try
     {
         IEnumerable <string> fileNames = assemblyResolver.GetAssembliesToSearch();
         searcher = SearchAndAddToStore(fileNames);
     }
     catch (Exception e)
     {
         log.Error("Caught exception while searching for plugins: '{0}'", e.Message);
         log.Debug(e);
         searcher = null;
     }
     finally
     {
         searchTask.Set();
     }
 }
コード例 #11
0
        /// <summary>
        /// Load from an XML package definition file.
        /// This file is not expected to have info about the plugins in it, so this method will enumerate the plugins inside each dll by loading them.
        /// </summary>
        /// <param name="xmlFilePath">The Package Definition xml file. Usually named package.xml</param>
        /// <param name="projectDir">Directory used byt GitVersionCalculator to expand any $(GitVersion) macros in the XML file.</param>
        /// <returns></returns>
        public static PackageDef FromInputXml(string xmlFilePath, string projectDir)
        {
            PackageDef.ValidateXml(xmlFilePath);
            var pkgDef = PackageDef.FromXml(xmlFilePath);

            if (pkgDef.Files.Any(f => f.HasCustomData <UseVersionData>() && f.HasCustomData <SetAssemblyInfoData>()))
            {
                throw new InvalidDataException("A file cannot specify <SetAssemblyInfo/> and <UseVersion/> at the same time.");
            }

            pkgDef.Files = expandGlobEntries(pkgDef.Files);

            var excludeAdd = pkgDef.Files.Where(file => file.IgnoredDependencies != null).SelectMany(file => file.IgnoredDependencies).Distinct().ToList();

            List <Exception> exceptions = new List <Exception>();

            foreach (PackageFile item in pkgDef.Files)
            {
                string fullPath = Path.GetFullPath(item.FileName);
                if (!File.Exists(fullPath))
                {
                    string fileName = Path.GetFileName(item.FileName);
                    if (File.Exists(fileName) && item.SourcePath == null)
                    {
                        // this is to support building everything to the root folder. This way the developer does not have to specify SourcePath.
                        log.Warning("Specified file '{0}' was not found, using file '{1}' as source instead. Consider setting SourcePath to remove this warning.", item.FileName, fileName);
                        item.SourcePath = fileName;
                    }
                    else
                    {
                        exceptions.Add(new FileNotFoundException("Missing file for package.", fullPath));
                    }
                }
            }
            if (exceptions.Count > 0)
            {
                throw new AggregateException("Missing files", exceptions);
            }

            pkgDef.Date = DateTime.UtcNow;

            // Copy to output directory first
            foreach (var file in pkgDef.Files)
            {
                if (file.RelativeDestinationPath != file.FileName)
                {
                    try
                    {
                        var destPath = Path.GetFullPath(file.RelativeDestinationPath);
                        if (!File.Exists(destPath))
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(destPath));
                            ProgramHelper.FileCopy(file.FileName, destPath);
                        }
                    }
                    catch
                    {
                        // Catching here. The files might be used by themselves
                    }
                }
            }

            var searcher = new PluginSearcher(PluginSearcher.Options.IncludeSameAssemblies);

            searcher.Search(Directory.GetCurrentDirectory());
            List <AssemblyData> assemblies = searcher.Assemblies.ToList();

            // Enumerate plugins if this has not already been done.
            if (!pkgDef.Files.SelectMany(pfd => pfd.Plugins).Any())
            {
                EnumeratePlugins(pkgDef, assemblies);
            }

            log.Info("Updating package version.");
            pkgDef.updateVersion(projectDir);
            log.Info("Package version is {0}", pkgDef.Version);

            pkgDef.findDependencies(excludeAdd, assemblies);

            return(pkgDef);
        }
コード例 #12
0
ファイル: PluginManager.cs プロジェクト: ZHJEE/OpenTAP
        /// <summary>
        /// Gets the AssemblyData for the OpenTap.dll assembly.
        /// This will search for plugins if not done already (i.e. call and wait for <see cref="PluginManager.SearchAsync()"/>)
        /// </summary>
        public static AssemblyData GetOpenTapAssembly()
        {
            PluginSearcher searcher = GetSearcher();

            return(searcher.PluginMarkerType.Assembly);
        }
コード例 #13
0
ファイル: PackageDefTests.cs プロジェクト: ZHJEE/OpenTAP
        public void CreatePackageDepReuse()
        {
            if (Directory.Exists("Packages2"))
            {
                Directory.Delete("Packages2", true);
            }

            Directory.Move("Packages", "Packages2");
            File.Copy("Packages2/DependencyTest.dll", "DependencyTest.dll", true);

            try
            {
                Directory.CreateDirectory("Packages");

                {
                    PackageDef def = new PackageDef()
                    {
                        Name = "pkg1", Version = SemanticVersion.Parse("1.2")
                    };
                    def.AddFile("OpenTap.dll");
                    Directory.CreateDirectory("Packages/pkg1");
                    using (var f = File.OpenWrite("Packages/pkg1/package.xml")) def.SaveTo(f);
                }

                {
                    PackageDef def = new PackageDef()
                    {
                        Name = "gui", Version = SemanticVersion.Parse("1.2")
                    };
                    def.AddFile("Keysight.OpenTap.Wpf.dll");
                    Directory.CreateDirectory("Packages/gui");
                    using (var f = File.OpenWrite("Packages/gui/package.xml")) def.SaveTo(f);
                }

                {
                    PackageDef def = new PackageDef()
                    {
                        Name = "rv", Version = SemanticVersion.Parse("1.2")
                    };
                    def.AddFile("Keysight.OpenTap.Wpf.dll");
                    Directory.CreateDirectory("Packages/rv");
                    using (var f = File.OpenWrite("Packages/rv/package.xml")) def.SaveTo(f);
                }

                {
                    PackageDef def = new PackageDef();
                    def.Name     = "test";
                    def.InfoLink = "a";
                    def.Date     = DateTime.Today;

                    def.Dependencies.Add(new PackageDependency("rv", VersionSpecifier.Parse("1.2")));

                    def.AddFile("DependencyTest.dll");
                    def.Files[0].DependentAssemblies.AddRange(PluginManager.GetSearcher().Assemblies.First(f => f.Name == "DependencyTest").References);

                    var searcher = new PluginSearcher();
                    searcher.Search(Directory.GetCurrentDirectory());
                    List <AssemblyData> assemblies = searcher.Assemblies.ToList();
                    def.findDependencies(new List <string>(), assemblies);

                    //Assert.AreEqual(3, def.Dependencies.Count);
                    Assert.IsTrue(def.Dependencies.Any(d => d.Name == "rv"));
                    Assert.IsTrue(def.Dependencies.Any(d => d.Name == "pkg1"));
                }

                {
                    PackageDef def = new PackageDef();
                    def.Name     = "test";
                    def.InfoLink = "a";
                    def.Date     = DateTime.Today;

                    def.Dependencies.Add(new PackageDependency("gui", VersionSpecifier.Parse("1.2")));

                    def.AddFile("DependencyTest.dll");
                    def.Files[0].DependentAssemblies.AddRange(PluginManager.GetSearcher().Assemblies.First(f => f.Name == "DependencyTest").References);

                    var searcher = new PluginSearcher();
                    searcher.Search(Directory.GetCurrentDirectory());
                    List <AssemblyData> assemblies = searcher.Assemblies.ToList();
                    def.findDependencies(new List <string>(), assemblies);

                    //Assert.AreEqual(2, def.Dependencies.Count);
                    Assert.IsTrue(def.Dependencies.Any(d => d.Name == "gui"));
                    Assert.IsTrue(def.Dependencies.Any(d => d.Name == "pkg1"));
                }
            }
            finally
            {
                if (Directory.Exists("Packages"))
                {
                    Directory.Delete("Packages", true);
                }
                Directory.Move("Packages2", "Packages");
            }
        }