From dc85233559d62679252a48e5e55d4140681b2f0f Mon Sep 17 00:00:00 2001 From: Vu Tran <56414817+vuqtran88@users.noreply.github.com> Date: Mon, 12 Apr 2021 15:34:01 -0700 Subject: [PATCH] Refactors the Multi Version Scanner (#526) * fix naming. * Supports target-framework configuration in config.yml. Add logic to report instrumentation mismatch. Refactoring. * rework on the assembly process logic so that the AssemblyAnalyzer only process one assembly at a time. * Removes the need of specifying target framework for each instrumentation set in the config.yml. The MVS will validate all target frameworks that the instrumented nuget package supports. --- .../ConsoleScanner/DownloadedNugetInfo.cs | 23 ++++ .../ConsoleScanner/InstrumentationSet.cs | 2 +- .../ConsoleScanner/NugetSet.cs | 2 +- .../ConsoleScanner/Program.cs | 110 +++++++++--------- .../Properties/launchSettings.json | 8 +- .../ConsoleScanner/ScannerConfiguration.cs | 7 +- .../ConsoleScanner/config.yml | 106 ++++++++--------- .../MultiverseScanner/AssemblyAnalyzer.cs | 77 +----------- .../InstrumentationValidator.cs | 30 +++-- .../Models/AssemblyAnalysis.cs | 12 +- .../MultiverseScanner/Models/AssemblyModel.cs | 58 +++++++-- .../Reporting/InstrumentationReport.cs | 3 + 12 files changed, 218 insertions(+), 220 deletions(-) create mode 100644 tests/Agent/MultiverseTesting/ConsoleScanner/DownloadedNugetInfo.cs diff --git a/tests/Agent/MultiverseTesting/ConsoleScanner/DownloadedNugetInfo.cs b/tests/Agent/MultiverseTesting/ConsoleScanner/DownloadedNugetInfo.cs new file mode 100644 index 0000000000..419db58486 --- /dev/null +++ b/tests/Agent/MultiverseTesting/ConsoleScanner/DownloadedNugetInfo.cs @@ -0,0 +1,23 @@ +// Copyright 2020 New Relic, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + + +using System.Collections.Generic; + +namespace NewRelic.Agent.ConsoleScanner +{ + public class DownloadedNugetInfo + { + public DownloadedNugetInfo(List dllFileLocations, string version, string packageName) + { + InstrumentedDllFileLocations = dllFileLocations; + PackageVersion = version; + PackageName = packageName; + } + + public List InstrumentedDllFileLocations { get; } + public string PackageVersion { get; } + public string PackageName { get; } + + } +} diff --git a/tests/Agent/MultiverseTesting/ConsoleScanner/InstrumentationSet.cs b/tests/Agent/MultiverseTesting/ConsoleScanner/InstrumentationSet.cs index d66f5faaaf..ad99037673 100644 --- a/tests/Agent/MultiverseTesting/ConsoleScanner/InstrumentationSet.cs +++ b/tests/Agent/MultiverseTesting/ConsoleScanner/InstrumentationSet.cs @@ -12,7 +12,7 @@ public class InstrumentationSet public string XmlFile { get; set; } - public List NugetAssemblies { get; set; } + public List NugetPackages { get; set; } public List LocalAssemblies { get; set; } } diff --git a/tests/Agent/MultiverseTesting/ConsoleScanner/NugetSet.cs b/tests/Agent/MultiverseTesting/ConsoleScanner/NugetSet.cs index a665b0781c..970fad1a46 100644 --- a/tests/Agent/MultiverseTesting/ConsoleScanner/NugetSet.cs +++ b/tests/Agent/MultiverseTesting/ConsoleScanner/NugetSet.cs @@ -8,7 +8,7 @@ namespace NewRelic.Agent.ConsoleScanner { public class NugetSet { - public string AssemblyName { get; set; } + public string PackageName { get; set; } public string[] Versions { get; set; } } } diff --git a/tests/Agent/MultiverseTesting/ConsoleScanner/Program.cs b/tests/Agent/MultiverseTesting/ConsoleScanner/Program.cs index 84900552a5..d76cceb743 100644 --- a/tests/Agent/MultiverseTesting/ConsoleScanner/Program.cs +++ b/tests/Agent/MultiverseTesting/ConsoleScanner/Program.cs @@ -49,42 +49,34 @@ public static void ProcessAssemblies(ScannerConfiguration configuration) { foreach (var instrumentationSet in configuration.InstrumentationSets) { - // TODO: deal with duplicate assembly names - // load the instrumentation.xml and create InstrumentationModel var instrumentationModel = ReadInstrumentationFile(instrumentationSet); - List dllFileLocations = new List(); - // nuget assemblies - var nugetDllFileLocations = GetNugetAssemblies(instrumentationSet, instrumentationModel.UniqueAssemblies); - if (nugetDllFileLocations != null) - { - dllFileLocations.AddRange(nugetDllFileLocations); - } + var downloadedNugetInfoList = GetNugetAssemblies(instrumentationSet, instrumentationModel.UniqueAssemblies); - // local assemblies - var localDllFileLocations = GetLocalAssemblies(instrumentationSet); - if (localDllFileLocations != null) + foreach(var downloadedNugetInfo in downloadedNugetInfoList) { - dllFileLocations.AddRange(localDllFileLocations); - } - var dllFileNames = dllFileLocations.ToArray(); + foreach (var intrumentedDllFileLocation in downloadedNugetInfo.InstrumentedDllFileLocations) + { + // Builds a model from the files + Console.WriteLine($"Starting scan of '{intrumentedDllFileLocation}'"); + var assemblyAnalyzer = new AssemblyAnalyzer(); + var assemblyAnalysis = assemblyAnalyzer.RunAssemblyAnalysis(intrumentedDllFileLocation); - // Builds a model from the files - Console.WriteLine($"Starting scan of '{string.Join(',', dllFileNames)}'"); - var assemblyAnalyzer = new AssemblyAnalyzer(); - var assemblyAnalysis = assemblyAnalyzer.RunAssemblyAnalysis(dllFileNames); + var instrumentationValidator = new InstrumentationValidator(assemblyAnalysis); - var instrumentationValidator = new InstrumentationValidator(assemblyAnalysis); + // just some debugging writes + Console.WriteLine($"Found {assemblyAnalysis.ClassesCount} classes"); + Console.WriteLine("Scan complete"); - // just some debugging writes - Console.WriteLine($"Found {assemblyAnalysis.ClassesCount} classes"); - Console.WriteLine("Scan complete"); + var targetFramework = Path.GetFileName(Path.GetDirectoryName(intrumentedDllFileLocation)); - // run the validation - var report = instrumentationValidator.CheckInstrumentation(instrumentationModel, instrumentationSet.Name); - _instrumentationReports.Add(report); + // run the validation + var report = instrumentationValidator.CheckInstrumentation(instrumentationModel, instrumentationSet.Name, targetFramework, downloadedNugetInfo.PackageVersion, downloadedNugetInfo.PackageName); + _instrumentationReports.Add(report); + } + } } } @@ -101,11 +93,12 @@ public static InstrumentationModel ReadInstrumentationFile(InstrumentationSet in return instrumentationModel; } - // TODO: not the best name, considering all it does - public static List GetNugetPackages(string name, string[] versions, List instrumentationAssemblies) + public static List GetNugetPackages(string packageName, string[] versions, List instrumentationAssemblies) { - var addressPrefix = $"{_nugetSource}/{name.ToLower()}"; - List dllFileLocations = new List(); + var addressPrefix = $"{_nugetSource}/{packageName.ToLower()}"; + + var downloadedNugetInfos = new List(); + try { var webClient = new WebClient(); @@ -115,13 +108,15 @@ public static List GetNugetPackages(string name, string[] versions, List foreach (var version in versions) { + var dllFileLocations = new List(); + // set up - var nugetDownloadedPackagePrefix = $"{name.ToLower()}.{version.ToLower()}"; + var nugetDownloadedPackagePrefix = $"{packageName.ToLower()}.{version.ToLower()}"; var nugetExtractDirectoryName = $"{_nugetDataDirectory}\\{nugetDownloadedPackagePrefix}"; var nugetDownloadedPackageFileName = $"{_nugetDataDirectory}\\{nugetDownloadedPackagePrefix}.zip"; // example address: https://api.nuget.org/v3-flatcontainer/mongodb.driver.core/2.6.0/mongodb.driver.core.2.6.0.nupkg - var address = $"{addressPrefix}/{version.ToLower()}/{name.ToLower()}.{version.ToLower()}.nupkg"; + var address = $"{addressPrefix}/{version.ToLower()}/{packageName.ToLower()}.{version.ToLower()}.nupkg"; // skip downloading on re-run if (!File.Exists(nugetDownloadedPackageFileName)) @@ -130,23 +125,25 @@ public static List GetNugetPackages(string name, string[] versions, List var result = webClient.DownloadData(address); File.WriteAllBytes(nugetDownloadedPackageFileName, result); - Console.WriteLine($"Downloaded package {name} {version}"); + Console.WriteLine($"Downloaded package {packageName} {version}"); + } + + // extract dlls from package - // extract dlls from package - - if (Directory.Exists(nugetExtractDirectoryName)) - { - Directory.Delete(nugetExtractDirectoryName, true); - } - Directory.CreateDirectory(nugetExtractDirectoryName); - ZipFile.ExtractToDirectory(nugetDownloadedPackageFileName, nugetExtractDirectoryName); + if (Directory.Exists(nugetExtractDirectoryName)) + { + Directory.Delete(nugetExtractDirectoryName, true); } + Directory.CreateDirectory(nugetExtractDirectoryName); + ZipFile.ExtractToDirectory(nugetDownloadedPackageFileName, nugetExtractDirectoryName); // TODO: this will get every version (net45, netstandard1.5) of the dll in the package, which may not be necessary; foreach (var instrumentationAssembly in instrumentationAssemblies) { dllFileLocations.AddRange(Directory.GetFiles(nugetExtractDirectoryName, instrumentationAssembly + ".dll", SearchOption.AllDirectories)); } + + downloadedNugetInfos.Add(new DownloadedNugetInfo(dllFileLocations, version, packageName)); } } catch (Exception ex) @@ -155,25 +152,20 @@ public static List GetNugetPackages(string name, string[] versions, List Console.WriteLine($"GetNugetPackages exception : {ex}"); } - return dllFileLocations; + return downloadedNugetInfos; } - public static List GetNugetAssemblies(InstrumentationSet instrumentationSet, List instrumentationAssemblies) + public static List GetNugetAssemblies(InstrumentationSet instrumentationSet, List instrumentationAssemblies) { - List fileList = new List(); - if (instrumentationSet.NugetAssemblies != null) + var downloadedNugetInfoList = new List(); + if (instrumentationSet.NugetPackages != null) { - foreach (var nugetAssembly in instrumentationSet.NugetAssemblies) + foreach (var nugetPackage in instrumentationSet.NugetPackages) { - fileList.AddRange(GetNugetPackages(nugetAssembly.AssemblyName, nugetAssembly.Versions, instrumentationAssemblies)); + downloadedNugetInfoList.AddRange(GetNugetPackages(nugetPackage.PackageName, nugetPackage.Versions, instrumentationAssemblies)); } } - return fileList; - } - - public static List GetLocalAssemblies(InstrumentationSet instrumentationSet) - { - return instrumentationSet.LocalAssemblies; + return downloadedNugetInfoList; } public static void PrintReport() @@ -181,11 +173,15 @@ public static void PrintReport() Console.WriteLine("============ REPORT ============"); foreach(var report in _instrumentationReports) { - Console.WriteLine($"Instrumentation Set: {report.InstrumentationSetName}"); - foreach(var assemblyReport in report.AssemblyReports) + Console.WriteLine($"Instrumentation set: {report.InstrumentationSetName}"); + Console.WriteLine($"Nuget package: {report.PackageName} ver {report.PackageVersion}"); + Console.WriteLine($"Target framework: {report.TargetFramework}"); + Console.WriteLine($""); + + foreach (var assemblyReport in report.AssemblyReports) { Console.Write("\t"); - Console.WriteLine($"Assembly Name: {assemblyReport.AssemblyName}; Assembly Version: {assemblyReport.AssemblyVersion}"); + Console.WriteLine($"Assembly Name: {assemblyReport.AssemblyName}"); var methodValidations = assemblyReport.GetMethodValidationsForPrint(); foreach (var line in methodValidations) @@ -193,6 +189,8 @@ public static void PrintReport() Console.WriteLine($"\t{line}"); } } + + Console.WriteLine($""); } } } diff --git a/tests/Agent/MultiverseTesting/ConsoleScanner/Properties/launchSettings.json b/tests/Agent/MultiverseTesting/ConsoleScanner/Properties/launchSettings.json index 71dcbf5760..cdb36d6cc5 100644 --- a/tests/Agent/MultiverseTesting/ConsoleScanner/Properties/launchSettings.json +++ b/tests/Agent/MultiverseTesting/ConsoleScanner/Properties/launchSettings.json @@ -3,9 +3,9 @@ "ConsoleScanner": { "commandName": "Project", "commandLineArgs": "\".\\config.yml\"", - "environmentVariables": { - "myvar": "sometvaluething" - } + "environmentVariables": { + "MVS_XML_PATH": "PATH_TO_THE_AGENT_WRAPPER_FOLDER" + } } } -} \ No newline at end of file +} diff --git a/tests/Agent/MultiverseTesting/ConsoleScanner/ScannerConfiguration.cs b/tests/Agent/MultiverseTesting/ConsoleScanner/ScannerConfiguration.cs index adcd4ec92f..9301bb23e3 100644 --- a/tests/Agent/MultiverseTesting/ConsoleScanner/ScannerConfiguration.cs +++ b/tests/Agent/MultiverseTesting/ConsoleScanner/ScannerConfiguration.cs @@ -38,12 +38,11 @@ public void ProcessInstrumentationSet(InstrumentationSet instrumentationSet) instrumentationSet.Name = GetSubstitutedValue(instrumentationSet.Name); instrumentationSet.XmlFile = GetSubstitutedValue(instrumentationSet.XmlFile); - if (instrumentationSet.NugetAssemblies != null) + if (instrumentationSet.NugetPackages != null) { - foreach (var nugetSet in instrumentationSet.NugetAssemblies) + foreach (var nugetSet in instrumentationSet.NugetPackages) { - nugetSet.AssemblyName = GetSubstitutedValue(nugetSet.AssemblyName); - // not processing versions at this time since its not likely to be replace with an env var + nugetSet.PackageName = GetSubstitutedValue(nugetSet.PackageName); } } diff --git a/tests/Agent/MultiverseTesting/ConsoleScanner/config.yml b/tests/Agent/MultiverseTesting/ConsoleScanner/config.yml index c52fda66f8..53da015030 100644 --- a/tests/Agent/MultiverseTesting/ConsoleScanner/config.yml +++ b/tests/Agent/MultiverseTesting/ConsoleScanner/config.yml @@ -2,108 +2,108 @@ # asp35 assemblies are installed with the app based on target framework and are not available from nuget # - name: asp35 # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\Asp35\Instrumentation.xml - # nuget-assemblies: + # nuget-packages: # local-assemblies: # - name: aspNetCore # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\AspNetCore\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: Microsoft.AspNetCore.Hosting, versions: [2.1.1, 2.2.0, 2.2.7] } - # - { assembly-name: Microsoft.AspNetCore.Mvc.Core, versions: [2.1.3, 2.1.16, 2.2.5] } + # nuget-packages: + # - { package-name: Microsoft.AspNetCore.Hosting, versions: [2.1.1, 2.2.0, 2.2.7] } + # - { package-name: Microsoft.AspNetCore.Mvc.Core, versions: [2.1.3, 2.1.16, 2.2.5] } # local-assemblies: # not available from nuget, dll in inst.xml isn't referenced by any test apps # - name: castleMonoRail # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\CastleMonoRail2\Instrumentation.xml - # nuget-assemblies: + # nuget-packages: # local-assemblies: # - name: couchbase # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\Couchbase\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: CouchbaseNetClient, versions: [2.3.8, 2.4.8, 2.5.12, 2.6.2, 2.7.23, 3.0.7, 3.1.2] } + # nuget-packages: + # - { package-name: CouchbaseNetClient, versions: [2.3.8, 2.4.8, 2.5.12, 2.6.2, 2.7.23, 3.0.7, 3.1.2] } # local-assemblies: # not available from nuget, assembly in inst.xml is System.dll # - name: httpWebRequest # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\HttpWebRequest\Instrumentation.xml - # nuget-assemblies: + # nuget-packages: # local-assemblies: - name: mongodb xml-file: ${{ MVS_XML_PATH }}\MongoDb\Instrumentation.xml - nuget-assemblies: - - { assembly-name: MongoDB.Driver, versions: [2.0.2, 2.1.1, 2.2.4, 2.3.0, 2.4.4, 2.5.1] } + nuget-packages: + - { package-name: MongoDB.Driver, versions: [2.0.2, 2.1.1, 2.2.4, 2.3.0, 2.4.4, 2.5.1] } local-assemblies: - name: mongodb26 xml-file: ${{ MVS_XML_PATH }}\MongoDb26\Instrumentation.xml - nuget-assemblies: - - { assembly-name: MongoDB.Driver, versions: [2.6.0, 2.7.3, 2.8.1, 2.9.3, 2.10.4, 2.11.6] } - - { assembly-name: MongoDB.Driver.Core, versions: [2.6.0, 2.7.3, 2.8.1, 2.9.3, 2.10.4, 2.11.6] } + nuget-packages: + - { package-name: MongoDB.Driver, versions: [2.6.0, 2.7.3, 2.8.1, 2.9.3, 2.10.4, 2.11.6] } + - { package-name: MongoDB.Driver.Core, versions: [2.6.0, 2.7.3, 2.8.1, 2.9.3, 2.10.4, 2.11.6] } local-assemblies: # assembly in inst.xml is System.Messaging.dll, can get newer ones from nuget (?), but typically located in the GAC # - name: msmq # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\Msmq\Instrumentation.xml - # nuget-assemblies: + # nuget-packages: # # different packages for different framework versions, package structure doesn't contain a 'lib' folder # # TODO: if supporting this pkg for checking, will need to update package unpacking to find the .dlls - # #- { assembly-name: microsoft.netframework.referenceassemblies.net45, versions: [1.0.0] } + # #- { package-name: microsoft.netframework.referenceassemblies.net45, versions: [1.0.0] } # local-assemblies: # - C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Messaging\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Messaging.dll # - name: nServiceBus # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\NServiceBus\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: NServiceBus, versions: [5.0.0, 5.1.9, 5.2.26, 6.0.10, 6.1.10, 6.2.8, 6.3.9, 6.4.5, 6.5.10, 7.0.3, 7.1.13, 7.2.5, 7.3.2, 7.4.4] } + # nuget-packages: + # - { package-name: NServiceBus, versions: [5.0.0, 5.1.9, 5.2.26, 6.0.10, 6.1.10, 6.2.8, 6.3.9, 6.4.5, 6.5.10, 7.0.3, 7.1.13, 7.2.5, 7.3.2, 7.4.4] } # local-assemblies: # - name: openRasta # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\OpenRasta\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: openrasta-hosting-aspnet, versions: [2.5.25, 2.5.2000] } + # nuget-packages: + # - { package-name: openrasta-hosting-aspnet, versions: [2.5.25, 2.5.2000] } # local-assemblies: # - name: owin # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\Owin\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: Microsoft.Owin.Hosting, versions: [2.0.2, 2.1.0, 3.0.1, 3.1.0, 4.1.1] } + # nuget-packages: + # - { package-name: Microsoft.Owin.Hosting, versions: [2.0.2, 2.1.0, 3.0.1, 3.1.0, 4.1.1] } # local-assemblies: - name: rabbitmq xml-file: ${{ MVS_XML_PATH }}\RabbitMq\Instrumentation.xml - nuget-assemblies: - - { assembly-name: RabbitMQ.Client, versions: [3.5.2, 3.6.9, 5.1.2, 5.2.0, 6.2.1] } + nuget-packages: + - { package-name: RabbitMQ.Client, versions: [3.5.2, 3.6.9, 5.1.2, 5.2.0, 6.2.1] } local-assemblies: # - name: restSharp # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\RestSharp\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: RestSharp, versions: [105.2.3, 106.11.7] } + # nuget-packages: + # - { package-name: RestSharp, versions: [105.2.3, 106.11.7] } # local-assemblies: # assembly in inst.xml is System.Web.Extensions.dll, can get newer ones from nuget (?), but typically located in the GAC # - name: scriptHandlerFactory # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\ScriptHandlerFactory\Instrumentation.xml - # nuget-assemblies: + # nuget-packages: # # different packages for different framework versions, package structure doesn't contain a 'lib' folder # # TODO: if supporting this pkg for checking, will need to update package unpacking to find the .dlls - # #- { assembly-name: microsoft.netframework.referenceassemblies.net45, versions: [1.0.0] } + # #- { package-name: microsoft.netframework.referenceassemblies.net45, versions: [1.0.0] } # local-assemblies: # - C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Web.Extensions\v4.0_4.0.0.0__31bf3856ad364e35\System.Web.Extensions.dll # - name: serviceStackRedis # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\ScriptHandlerFactory\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: ServiceStack.Redis, versions: [4.0.40, 4.5.14, 5.10.4] } + # nuget-packages: + # - { package-name: ServiceStack.Redis, versions: [4.0.40, 4.5.14, 5.10.4] } # local-assemblies: # - name: stackExchangeRedis # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\StackExchangeRedis\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: StackExchange.Redis, versions: [1.0.488, 1.1.608, 1.2.6, 2.0.601, 2.2.4] } - # - { assembly-name: StackExchange.Redis.StrongName, versions: [1.0.488, 1.1.608, 1.2.6] } + # nuget-packages: + # - { package-name: StackExchange.Redis, versions: [1.0.488, 1.1.608, 1.2.6, 2.0.601, 2.2.4] } + # - { package-name: StackExchange.Redis.StrongName, versions: [1.0.488, 1.1.608, 1.2.6] } # local-assemblies: # 1 assembly in inst.xml is System.ServiceModel.dll @@ -111,33 +111,33 @@ # System.ServiceModel.Activation.dll (WCF4) isn't in my GAC (?) # - name: wcf3 # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\Wcf3\Instrumentation.xml - # nuget-assemblies: - # #- { assembly-name: runtime.win10-x64.Microsoft.NETCore.UniversalWindowsPlatform, versions: [?] } + # nuget-packages: + # #- { package-name: runtime.win10-x64.Microsoft.NETCore.UniversalWindowsPlatform, versions: [?] } # local-assemblies: # - C:\Windows\assembly\GAC_MSIL\System.ServiceModel\3.0.0.0__b77a5c561934e089\System.ServiceModel.dll # - name: webApi1 # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\WebApi1\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: Microsoft.AspNet.WebApi.Core, versions: [4.0.20710, 4.0.30506] } + # nuget-packages: + # - { package-name: Microsoft.AspNet.WebApi.Core, versions: [4.0.20710, 4.0.30506] } # local-assemblies: # - name: webApi2 # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\WebApi2\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: Microsoft.AspNet.WebApi.Core, versions: [5.1.2, 5.2.7] } + # nuget-packages: + # - { package-name: Microsoft.AspNet.WebApi.Core, versions: [5.1.2, 5.2.7] } # local-assemblies: # - name: webOptimization # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\WebOptimization\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: Microsoft.AspNet.Web.Optimization, versions: [1.1.0, 1.1.3] } + # nuget-packages: + # - { package-name: Microsoft.AspNet.Web.Optimization, versions: [1.1.0, 1.1.3] } # local-assemblies: # - name: webServices # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\WebOptimization\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: microsoft.netframework.referenceassemblies.net45, versions: [1.0.0] } + # nuget-packages: + # - { package-name: microsoft.netframework.referenceassemblies.net45, versions: [1.0.0] } # local-assemblies: # - C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Web.Extensions\v4.0_4.0.0.0__31bf3856ad364e35\System.Web.Extensions.dll # - C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Web.Services\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.Services.dll @@ -145,20 +145,20 @@ # TODO: figure out what dlls to test re: .net fw & .net core # - name: httpClient # xml-file: C:\Users\LyniceSpangler\source\repos\dotnet-multiverse-scanner\TestData\HttpClient\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: microsoft.netframework.referenceassemblies.net45, versions: [1.0.0] } - # - { assembly-name: microsoft.netnetcore.app, versions: [2.1.25, 2.2.8] } + # nuget-packages: + # - { package-name: microsoft.netframework.referenceassemblies.net45, versions: [1.0.0] } + # - { package-name: microsoft.netnetcore.app, versions: [2.1.25, 2.2.8] } # local-assemblies: # # TODO: add assembly for Oracle.DataAccess & Oracle.ManagedDataAccess & IBM.Data.DB2 # - name: sql # xml-file: C:\git\newrelic-dotnet-agent\src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\Sql\Instrumentation.xml - # nuget-assemblies: - # - { assembly-name: microsoft.netframework.referenceassemblies.net45, versions: [1.0.0] } - # #- { assembly-name: microsoft.netnetcore.app, versions: [2.1.25, 2.2.8] } - # - { assembly-name: System.Data.SqlClient, versions: [4.4.0, 4.5.3, 4.6.1, 4.7.0, 4.8.2] } - # #- { assembly-name: Devart.Data.MySql, versions: [8.9.12, 8.19.1812] } - # - { assembly-name: MySql.Data, versions: [6.9.12, 8.0.18, 8.0.23] } - # - { assembly-name: MySqlConnector, versions: [0.69.10, 1.0.1, 1.2.1] } - # - { assembly-name: Npgsql, versions: [4.0.5, 4.1.8, 5.0.3] } + # nuget-packages: + # - { package-name: microsoft.netframework.referenceassemblies.net45, versions: [1.0.0] } + # #- { package-name: microsoft.netnetcore.app, versions: [2.1.25, 2.2.8] } + # - { package-name: System.Data.SqlClient, versions: [4.4.0, 4.5.3, 4.6.1, 4.7.0, 4.8.2] } + # #- { package-name: Devart.Data.MySql, versions: [8.9.12, 8.19.1812] } + # - { package-name: MySql.Data, versions: [6.9.12, 8.0.18, 8.0.23] } + # - { package-name: MySqlConnector, versions: [0.69.10, 1.0.1, 1.2.1] } + # - { package-name: Npgsql, versions: [4.0.5, 4.1.8, 5.0.3] } # local-assemblies: diff --git a/tests/Agent/MultiverseTesting/MultiverseScanner/AssemblyAnalyzer.cs b/tests/Agent/MultiverseTesting/MultiverseScanner/AssemblyAnalyzer.cs index 909a0aa4ad..2f10f0520d 100644 --- a/tests/Agent/MultiverseTesting/MultiverseScanner/AssemblyAnalyzer.cs +++ b/tests/Agent/MultiverseTesting/MultiverseScanner/AssemblyAnalyzer.cs @@ -4,8 +4,6 @@ using Mono.Cecil; using NewRelic.Agent.MultiverseScanner.Models; -using System; -using System.Linq; namespace NewRelic.Agent.MultiverseScanner { @@ -13,23 +11,11 @@ namespace NewRelic.Agent.MultiverseScanner public class AssemblyAnalyzer { - public AssemblyAnalysis RunAssemblyAnalysis(params string[] filePaths) + public AssemblyAnalysis RunAssemblyAnalysis(string filePath) { - var assemblyAnalysis = new AssemblyAnalysis(); + var assemblyModel = GetAssemblyModel(filePath); - foreach (var filePath in filePaths) - { - var assemblyModel = GetAssemblyModel(filePath); - - // TODO: need to allow duplicates for multiple versions - // for now, don't add it if it's in there - // refactor - Dictionary may not be the right data structure - if (assemblyAnalysis.AssemblyModels.ContainsKey(assemblyModel.AssemblyName)) - { - continue; - } - assemblyAnalysis.AssemblyModels.Add(assemblyModel.AssemblyName, assemblyModel); - } + var assemblyAnalysis = new AssemblyAnalysis(assemblyModel); return assemblyAnalysis; } @@ -37,63 +23,8 @@ public AssemblyAnalysis RunAssemblyAnalysis(params string[] filePaths) public AssemblyModel GetAssemblyModel(string filePath) { var moduleDefinition = ModuleDefinition.ReadModule(filePath); - var assemblyModel = new AssemblyModel(moduleDefinition.Assembly.Name.Name, GetAssemblyVersion(moduleDefinition)); - BuildClassModels(assemblyModel, moduleDefinition); + var assemblyModel = new AssemblyModel(moduleDefinition); return assemblyModel; } - - public void BuildClassModels(AssemblyModel assemblyModel, ModuleDefinition moduleDefinition) - { - foreach (var typeDefinition in moduleDefinition.Types) - { - if (!typeDefinition.IsClass || typeDefinition.FullName.StartsWith("<")) - { - continue; - } - - var classModel = new ClassModel(typeDefinition.FullName, GetAccessLevel(typeDefinition)); - BuildMethodModels(classModel, typeDefinition); - assemblyModel.AddClass(classModel); - } - } - - public void BuildMethodModels(ClassModel classModel, TypeDefinition typeDefinition) - { - foreach (var method in typeDefinition.Methods) - { - var methodModel = classModel.GetOrCreateMethodModel(method.Name); - if (method.HasParameters) - { - var parameters = method.Parameters.Select((x) => x.ParameterType.FullName.Replace('<', '[').Replace('>', ']')).ToList(); - methodModel.ParameterSets.Add(string.Join(",", parameters)); - } - else - { - // covers a method having no parameters. - methodModel.ParameterSets.Add(string.Empty); - } - } - } - - public string GetAccessLevel(TypeDefinition typeDefinition) - { - if (typeDefinition.IsPublic) - { - return "public"; - } - else if (typeDefinition.IsNotPublic) - { - return "private"; - } - - - return ""; - } - - public Version GetAssemblyVersion(ModuleDefinition moduleDefinition) - { - var assemblyName = new System.Reflection.AssemblyName(moduleDefinition.Assembly.FullName); - return assemblyName.Version; - } } } diff --git a/tests/Agent/MultiverseTesting/MultiverseScanner/InstrumentationValidator.cs b/tests/Agent/MultiverseTesting/MultiverseScanner/InstrumentationValidator.cs index e67fa07d8c..47131e61a0 100644 --- a/tests/Agent/MultiverseTesting/MultiverseScanner/InstrumentationValidator.cs +++ b/tests/Agent/MultiverseTesting/MultiverseScanner/InstrumentationValidator.cs @@ -17,24 +17,26 @@ public InstrumentationValidator(AssemblyAnalysis assemblyAnalysis) _assemblyAnalysis = assemblyAnalysis; } - public InstrumentationReport CheckInstrumentation(InstrumentationModel instrumentationModel, string instrumentationSetName) + public InstrumentationReport CheckInstrumentation(InstrumentationModel instrumentationModel, string instrumentationSetName, string targetFramework, string packageVersion, string packageName) { - var instrumentationReport = new InstrumentationReport() { InstrumentationSetName = instrumentationSetName }; - - // Check each AssemblyModel against all instrumentation - // InstrumentationReport will show aggregated results from all assemblies - foreach (var assemblyModel in _assemblyAnalysis.AssemblyModels.Values) + var instrumentationReport = new InstrumentationReport() { - var assemblyReport = new AssemblyReport(); + InstrumentationSetName = instrumentationSetName, + TargetFramework = targetFramework, + PackageVersion = packageVersion, + PackageName = packageName + }; - assemblyReport.AssemblyName = assemblyModel.AssemblyName; - assemblyReport.AssemblyVersion = assemblyModel.AssemblyVersion; - CheckMatch(assemblyModel, instrumentationModel, assemblyReport); + // Check each AssemblyModel against all instrumentation + var assemblyReport = new AssemblyReport(); - instrumentationReport.AssemblyReports.Add(assemblyReport); - } + assemblyReport.AssemblyName = _assemblyAnalysis.AssemblyModel.AssemblyName; + + CheckMatch(_assemblyAnalysis.AssemblyModel, instrumentationModel, assemblyReport); + instrumentationReport.AssemblyReports.Add(assemblyReport); + return instrumentationReport; } @@ -75,6 +77,10 @@ public void ValidateClass(AssemblyModel assemblyModel, Match match, AssemblyRepo return; } + foreach (var exactMethodMatcher in match.ExactMethodMatchers) + { + instrumentationReport.AddMethodValidation(match, exactMethodMatcher, false); + } // class did not match so marking all methods as false - can be changed by later validation attempts //MarkAllMethodsAsNotValid(match, instrumentationReport); } diff --git a/tests/Agent/MultiverseTesting/MultiverseScanner/Models/AssemblyAnalysis.cs b/tests/Agent/MultiverseTesting/MultiverseScanner/Models/AssemblyAnalysis.cs index 365ae1ffcb..c849eb29fd 100644 --- a/tests/Agent/MultiverseTesting/MultiverseScanner/Models/AssemblyAnalysis.cs +++ b/tests/Agent/MultiverseTesting/MultiverseScanner/Models/AssemblyAnalysis.cs @@ -9,18 +9,16 @@ namespace NewRelic.Agent.MultiverseScanner.Models { public class AssemblyAnalysis { - public Dictionary AssemblyModels { get; } + public AssemblyModel AssemblyModel { get; } - public AssemblyAnalysis() + public AssemblyAnalysis(AssemblyModel assemblyModel) { - AssemblyModels = new Dictionary(); + AssemblyModel = assemblyModel; } - - - // TODO: is this needed for anything except logging to output? + public int ClassesCount { - get { return AssemblyModels.Select((x) => x.Value.ClassModels.Count).ToList().Sum(); } + get { return AssemblyModel.ClassModels.Count; } } } } diff --git a/tests/Agent/MultiverseTesting/MultiverseScanner/Models/AssemblyModel.cs b/tests/Agent/MultiverseTesting/MultiverseScanner/Models/AssemblyModel.cs index f38c2c17bb..f18c6e6fcd 100644 --- a/tests/Agent/MultiverseTesting/MultiverseScanner/Models/AssemblyModel.cs +++ b/tests/Agent/MultiverseTesting/MultiverseScanner/Models/AssemblyModel.cs @@ -4,27 +4,67 @@ using System; using System.Collections.Generic; +using System.Linq; +using Mono.Cecil; namespace NewRelic.Agent.MultiverseScanner.Models { public class AssemblyModel { - public string AssemblyName { get; } - - public Version AssemblyVersion { get; } - + ModuleDefinition _moduleDefinition; + public string AssemblyName => _moduleDefinition.Assembly.Name.Name; public Dictionary ClassModels { get; } - public AssemblyModel(string assemblyName, Version assemblyVersion) + public AssemblyModel(ModuleDefinition moduleDefinition) { - AssemblyName = assemblyName; - AssemblyVersion = assemblyVersion; + _moduleDefinition = moduleDefinition; ClassModels = new Dictionary(); + + foreach (var typeDefinition in _moduleDefinition.Types) + { + if (!typeDefinition.IsClass || typeDefinition.FullName.StartsWith("<")) + { + continue; + } + + var classModel = new ClassModel(typeDefinition.FullName, GetAccessLevel(typeDefinition)); + BuildMethodModels(classModel, typeDefinition); + ClassModels.Add(classModel.Name, classModel); + } + } + + private string GetAccessLevel(TypeDefinition typeDefinition) + { + if (typeDefinition.IsPublic) + { + return "public"; + } + else if (typeDefinition.IsNotPublic) + { + return "private"; + } + + + return ""; } - public void AddClass(ClassModel classModel) + private void BuildMethodModels(ClassModel classModel, TypeDefinition typeDefinition) { - ClassModels.Add(classModel.Name, classModel); + foreach (var method in typeDefinition.Methods) + { + var methodModel = classModel.GetOrCreateMethodModel(method.Name); + if (method.HasParameters) + { + var parameters = method.Parameters.Select((x) => x.ParameterType.FullName.Replace('<', '[').Replace('>', ']')).ToList(); + methodModel.ParameterSets.Add(string.Join(",", parameters)); + } + else + { + // covers a method having no parameters. + methodModel.ParameterSets.Add(string.Empty); + } + } } + } } diff --git a/tests/Agent/MultiverseTesting/MultiverseScanner/Reporting/InstrumentationReport.cs b/tests/Agent/MultiverseTesting/MultiverseScanner/Reporting/InstrumentationReport.cs index f8d2a37b6d..f26c54e806 100644 --- a/tests/Agent/MultiverseTesting/MultiverseScanner/Reporting/InstrumentationReport.cs +++ b/tests/Agent/MultiverseTesting/MultiverseScanner/Reporting/InstrumentationReport.cs @@ -12,6 +12,9 @@ namespace NewRelic.Agent.MultiverseScanner.Reporting public class InstrumentationReport { public string InstrumentationSetName; + public string PackageVersion; + public string TargetFramework; + public string PackageName; public List AssemblyReports = new List(); }