Added dependencyScope detection for maven components (#87)
* Added "DependencyScope" for scanned component. Currently detection is only active for maven components. * Added telemetry to keep track of each recorded component.
This commit is contained in:
Родитель
63dcae650a
Коммит
3a17feb7e1
|
@ -41,5 +41,6 @@
|
|||
<PackageVersion Include="System.Runtime.Loader" Version="4.3.0"/>
|
||||
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="4.9.0"/>
|
||||
<PackageVersion Include="yamldotnet" Version="11.2.1"/>
|
||||
<PackageVersion Include="Faker.net" Version="2.0.154"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Collections.Immutable;
|
|||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.ComponentDetection.Contracts;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
using Microsoft.ComponentDetection.Contracts.TypedComponent;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.ComponentDetection.Common.Tests")]
|
||||
|
@ -133,7 +134,8 @@ namespace Microsoft.ComponentDetection.Common.DependencyGraph
|
|||
DetectedComponent detectedComponent,
|
||||
bool isExplicitReferencedDependency = false,
|
||||
string parentComponentId = null,
|
||||
bool? isDevelopmentDependency = null)
|
||||
bool? isDevelopmentDependency = null,
|
||||
DependencyScope? dependencyScope = null)
|
||||
{
|
||||
if (detectedComponent == null)
|
||||
{
|
||||
|
@ -167,7 +169,7 @@ namespace Microsoft.ComponentDetection.Common.DependencyGraph
|
|||
lock (registerUsageLock)
|
||||
{
|
||||
storedComponent = detectedComponentsInternal.GetOrAdd(componentId, detectedComponent);
|
||||
AddComponentToGraph(ManifestFileLocation, detectedComponent, isExplicitReferencedDependency, parentComponentId, isDevelopmentDependency);
|
||||
AddComponentToGraph(ManifestFileLocation, detectedComponent, isExplicitReferencedDependency, parentComponentId, isDevelopmentDependency, dependencyScope);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,13 +188,20 @@ namespace Microsoft.ComponentDetection.Common.DependencyGraph
|
|||
return recorder;
|
||||
}
|
||||
|
||||
private void AddComponentToGraph(string location, DetectedComponent detectedComponent, bool isExplicitReferencedDependency, string parentComponentId, bool? isDevelopmentDependency)
|
||||
private void AddComponentToGraph(
|
||||
string location,
|
||||
DetectedComponent detectedComponent,
|
||||
bool isExplicitReferencedDependency,
|
||||
string parentComponentId,
|
||||
bool? isDevelopmentDependency,
|
||||
DependencyScope? dependencyScope)
|
||||
{
|
||||
var componentNode = new DependencyGraph.ComponentRefNode
|
||||
{
|
||||
Id = detectedComponent.Component.Id,
|
||||
IsExplicitReferencedDependency = isExplicitReferencedDependency,
|
||||
IsDevelopmentDependency = isDevelopmentDependency,
|
||||
DependencyScope = dependencyScope,
|
||||
};
|
||||
|
||||
DependencyGraph.AddComponent(componentNode, parentComponentId);
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Collections.Immutable;
|
|||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.ComponentDetection.Contracts;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.ComponentDetection.Common.Tests")]
|
||||
|
||||
|
@ -46,6 +47,11 @@ namespace Microsoft.ComponentDetection.Common.DependencyGraph
|
|||
currentNode.IsDevelopmentDependency = currentNode.IsDevelopmentDependency.GetValueOrDefault(true) && componentNode.IsDevelopmentDependency.Value;
|
||||
}
|
||||
|
||||
if (componentNode.DependencyScope.HasValue)
|
||||
{
|
||||
currentNode.DependencyScope = DependencyScopeComparer.GetMergedDependencyScope(currentNode.DependencyScope, componentNode.DependencyScope);
|
||||
}
|
||||
|
||||
return currentNode;
|
||||
});
|
||||
|
||||
|
@ -101,6 +107,11 @@ namespace Microsoft.ComponentDetection.Common.DependencyGraph
|
|||
return componentNodes[componentId].IsDevelopmentDependency;
|
||||
}
|
||||
|
||||
public DependencyScope? GetDependencyScope(string componentId)
|
||||
{
|
||||
return componentNodes[componentId].DependencyScope;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetAllExplicitlyReferencedComponents()
|
||||
{
|
||||
return componentNodes.Values
|
||||
|
@ -175,6 +186,8 @@ namespace Microsoft.ComponentDetection.Common.DependencyGraph
|
|||
|
||||
internal bool? IsDevelopmentDependency { get; set; }
|
||||
|
||||
internal DependencyScope? DependencyScope { get; set; }
|
||||
|
||||
internal ComponentRefNode()
|
||||
{
|
||||
DependencyIds = new HashSet<string>();
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Merges dependnecy Scope in their order of Priority.
|
||||
/// Higher priority scope, as indicated by its lower enum value is given precendence.
|
||||
/// </summary>
|
||||
public class DependencyScopeComparer
|
||||
{
|
||||
public static DependencyScope? GetMergedDependencyScope(DependencyScope? scope1, DependencyScope? scope2) {
|
||||
if (!scope1.HasValue)
|
||||
{
|
||||
return scope2;
|
||||
}
|
||||
else if (!scope2.HasValue)
|
||||
{
|
||||
return scope1;
|
||||
}
|
||||
|
||||
return (int)scope1 < (int)scope2 ? scope1 : scope2;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Common.Telemetry.Records
|
||||
{
|
||||
public class DetectedComponentScopeRecord : BaseDetectionTelemetryRecord
|
||||
{
|
||||
public override string RecordName => "ComponentScopeRecord";
|
||||
|
||||
public int? MavenProvidedScopeCount { get; set; } = 0;
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public void IncrementProvidedScopeCount()
|
||||
{
|
||||
MavenProvidedScopeCount++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Contracts.BcdeModels
|
||||
{
|
||||
/// <summary>Used to communicate Dependency Scope of Component.
|
||||
/// Currently only populated for Maven component.
|
||||
/// The values are ordered in terms of priority, which is used to resolve the scope for duplicate component while merging them.
|
||||
/// </summary>
|
||||
public enum DependencyScope
|
||||
{
|
||||
/// <summary>default scope. dependencies are available in the project during all build tasks. propogated to dependent projects. </summary>
|
||||
MavenCompile = 0,
|
||||
|
||||
/// <summary> Required at Runtime, but not at compile time.</summary>
|
||||
MavenRuntime = 1,
|
||||
|
||||
/// <summary>Dependencies are available only at compile time and in the test classpath of the project. These dependencies are also not transitive.</summary>
|
||||
MavenProvided = 2,
|
||||
|
||||
/// <summary>Similar to provided scope. Requires explicit reference to Jar. </summary>
|
||||
MavenSystem = 3,
|
||||
|
||||
/// <summary>Used only at runtime.</summary>
|
||||
MavenTest = 4,
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Contracts.BcdeModels
|
||||
|
@ -15,6 +16,9 @@ namespace Microsoft.ComponentDetection.Contracts.BcdeModels
|
|||
|
||||
public bool? IsDevelopmentDependency { get; set; }
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public DependencyScope? DependencyScope { get; set; }
|
||||
|
||||
public IEnumerable<TypedComponent.TypedComponent> TopLevelReferrers { get; set; }
|
||||
|
||||
public IEnumerable<int> ContainerDetailIds { get; set; }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Contracts
|
||||
{
|
||||
|
@ -56,6 +57,9 @@ namespace Microsoft.ComponentDetection.Contracts
|
|||
|
||||
/// <summary> Gets or sets the layer within a container where this component was found.</summary>
|
||||
public IDictionary<int, IEnumerable<int>> ContainerLayerIds { get; set; }
|
||||
|
||||
/// <summary> Gets or sets Dependency Scope of the component.</summary>
|
||||
public DependencyScope? DependencyScope { get; set; }
|
||||
|
||||
/// <summary>Adds a filepath to the FilePaths hashset for this detected component.</summary>
|
||||
/// <param name="filePath">The file path to add to the hashset.</param>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Contracts
|
||||
{
|
||||
|
@ -25,12 +26,14 @@ namespace Microsoft.ComponentDetection.Contracts
|
|||
/// <param name="isExplicitReferencedDependency">The value define if the component was referenced manually by the user in the location where the scanning is taking place.</param>
|
||||
/// <param name="parentComponentId">Id of the parent component.</param>
|
||||
/// <param name="isDevelopmentDependency">Boolean value indicating whether or not a component is a development-time dependency. Null implies that the value is unknown.</param>
|
||||
/// <param name="dependencyScope">Enum value indicating scope of the component. </param>
|
||||
/// <returns>DetectedComponent added or updated.</returns>
|
||||
void RegisterUsage(
|
||||
DetectedComponent detectedComponent,
|
||||
bool isExplicitReferencedDependency = false,
|
||||
string parentComponentId = null,
|
||||
bool? isDevelopmentDependency = null);
|
||||
bool? isDevelopmentDependency = null,
|
||||
DependencyScope? dependencyScope = null);
|
||||
|
||||
DetectedComponent GetComponent(string componentId);
|
||||
|
||||
|
@ -82,6 +85,13 @@ namespace Microsoft.ComponentDetection.Contracts
|
|||
/// <returns>True if a development dependency, false if not. Null when unknown.</returns>
|
||||
bool? IsDevelopmentDependency(string componentId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns DepedencyScope for the given componentId.
|
||||
/// Null can be returned if a detector doesn't have the scope infromation.
|
||||
/// </summary>
|
||||
/// <param name="componentId">The componentId to check.</param>
|
||||
DependencyScope? GetDependencyScope(string componentId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the component IDs of all explicitly referenced components.
|
||||
/// </summary>
|
||||
|
|
|
@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.ComponentDetection.Contracts;
|
||||
using Microsoft.ComponentDetection.Contracts.Internal;
|
||||
using Microsoft.ComponentDetection.Contracts.TypedComponent;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Detectors.Ivy
|
||||
|
@ -33,7 +34,7 @@ namespace Microsoft.ComponentDetection.Detectors.Ivy
|
|||
/// in the project's build.xml, or if they use any file inclusion mechanism, it will fail.
|
||||
///
|
||||
/// The file written out by the custom Ant task is a simple JSON file representing a series of calls to be made to
|
||||
/// the <see cref="ISingleFileComponentRecorder.RegisterUsage(DetectedComponent, bool, string, bool?)"/> method.
|
||||
/// the <see cref="ISingleFileComponentRecorder.RegisterUsage(DetectedComponent, bool, string, bool?, DependencyScope?)"/> method.
|
||||
/// </remarks>
|
||||
[Export(typeof(IComponentDetector))]
|
||||
public class IvyDetector : FileComponentDetector, IExperimentalDetector
|
||||
|
|
|
@ -1,27 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using Microsoft.ComponentDetection.Contracts;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
using Microsoft.ComponentDetection.Contracts.TypedComponent;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Detectors.Maven
|
||||
{
|
||||
public static class MavenParsingUtilities
|
||||
{
|
||||
public static (DetectedComponent Component, bool? IsDevelopmentDependency) GenerateDetectedComponentFromMavenString(string key)
|
||||
private static readonly Dictionary<string, DependencyScope> MavenScopeToDependencyScopeMapping = new Dictionary<string, DependencyScope>()
|
||||
{
|
||||
var component = GetMavenComponentFromComponentString(key);
|
||||
{ "compile", DependencyScope.MavenCompile },
|
||||
{ "provided", DependencyScope.MavenProvided },
|
||||
{ "system", DependencyScope.MavenSystem },
|
||||
{ "test", DependencyScope.MavenTest },
|
||||
{ "runtime", DependencyScope.MavenRuntime },
|
||||
};
|
||||
|
||||
var detectedComponent = new DetectedComponent(component.component);
|
||||
public static (DetectedComponent Component, bool? IsDevelopmentDependency, DependencyScope? dependencyScope) GenerateDetectedComponentAndMetadataFromMavenString(string key)
|
||||
{
|
||||
var componentAndMetaData = GetMavenComponentAndIsDevDependencyAndScope(key);
|
||||
|
||||
return (detectedComponent, component.isDevDependency);
|
||||
var detectedComponent = new DetectedComponent(componentAndMetaData.component);
|
||||
|
||||
return (detectedComponent, componentAndMetaData.isDevDependency, componentAndMetaData.dependencyScope);
|
||||
}
|
||||
|
||||
private static (MavenComponent component, bool? isDevDependency) GetMavenComponentFromComponentString(string componentString)
|
||||
private static (MavenComponent component, bool? isDevDependency, DependencyScope? dependencyScope) GetMavenComponentAndIsDevDependencyAndScope(string componentString)
|
||||
{
|
||||
var info = GetMavenComponentStringInfo(componentString);
|
||||
return (new MavenComponent(info.groupId, info.artifactId, info.version), info.isDevelopmentDependency);
|
||||
return (new MavenComponent(info.groupId, info.artifactId, info.version), info.isDevelopmentDependency, info.dependencyScope);
|
||||
}
|
||||
|
||||
private static (string groupId, string artifactId, string version, bool? isDevelopmentDependency)
|
||||
private static (string groupId, string artifactId, string version, bool? isDevelopmentDependency, DependencyScope dependencyScope)
|
||||
GetMavenComponentStringInfo(string mavenComponentString)
|
||||
{
|
||||
var results = mavenComponentString.Split(':');
|
||||
|
@ -37,16 +49,21 @@ namespace Microsoft.ComponentDetection.Detectors.Maven
|
|||
results = new[] { results[0], results[1], results[2], results[4], results[5] };
|
||||
}
|
||||
|
||||
// 'MavenCompile' is a default scope for maven dependencies.
|
||||
DependencyScope dependencyScope = DependencyScope.MavenCompile;
|
||||
var groupId = results[0];
|
||||
var artifactId = results[1];
|
||||
var version = results[3];
|
||||
bool? isDevDependency = null;
|
||||
if (results.Length == 5)
|
||||
{
|
||||
isDevDependency = string.Equals(results[4], "test", StringComparison.OrdinalIgnoreCase);
|
||||
dependencyScope = MavenScopeToDependencyScopeMapping.TryGetValue(results[4], out dependencyScope)
|
||||
? dependencyScope
|
||||
: throw new InvalidOperationException($"Invalid scope ('{results[4]}') found for '{mavenComponentString}' found in generated dependency graph.");
|
||||
isDevDependency = dependencyScope == DependencyScope.MavenTest;
|
||||
}
|
||||
|
||||
return (groupId, artifactId, version, isDevDependency);
|
||||
return (groupId, artifactId, version, isDevDependency, dependencyScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,9 +58,12 @@ namespace Microsoft.ComponentDetection.Detectors.Maven
|
|||
var localLine = line.Trim(TrimCharacters);
|
||||
if (!string.IsNullOrWhiteSpace(localLine) && topLevelComponent == null)
|
||||
{
|
||||
var topLevelMavenStringTuple = MavenParsingUtilities.GenerateDetectedComponentFromMavenString(localLine);
|
||||
topLevelComponent = topLevelMavenStringTuple.Component;
|
||||
singleFileComponentRecorder.RegisterUsage(topLevelMavenStringTuple.Component, isDevelopmentDependency: topLevelMavenStringTuple.IsDevelopmentDependency);
|
||||
var topLevelMavenStringInfo = MavenParsingUtilities.GenerateDetectedComponentAndMetadataFromMavenString(localLine);
|
||||
topLevelComponent = topLevelMavenStringInfo.Component;
|
||||
singleFileComponentRecorder.RegisterUsage(
|
||||
topLevelMavenStringInfo.Component,
|
||||
isDevelopmentDependency: topLevelMavenStringInfo.IsDevelopmentDependency,
|
||||
dependencyScope: topLevelMavenStringInfo.dependencyScope);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -104,18 +107,27 @@ namespace Microsoft.ComponentDetection.Detectors.Maven
|
|||
tupleStack.Pop();
|
||||
}
|
||||
|
||||
var componentAndDevDependencyTuple = MavenParsingUtilities.GenerateDetectedComponentFromMavenString(versionedComponent);
|
||||
var componentAndDevDependencyTuple = MavenParsingUtilities.GenerateDetectedComponentAndMetadataFromMavenString(versionedComponent);
|
||||
var newTuple = (ParseLevel: position, componentAndDevDependencyTuple.Component);
|
||||
|
||||
if (tupleStack.Count > 0)
|
||||
{
|
||||
var parent = tupleStack.Peek().Component;
|
||||
componentRecorder.RegisterUsage(parent);
|
||||
componentRecorder.RegisterUsage(newTuple.Component, parentComponentId: parent.Component.Id, isDevelopmentDependency: componentAndDevDependencyTuple.IsDevelopmentDependency);
|
||||
componentRecorder.RegisterUsage(
|
||||
newTuple.Component,
|
||||
parentComponentId: parent.Component.Id,
|
||||
isDevelopmentDependency: componentAndDevDependencyTuple.IsDevelopmentDependency,
|
||||
dependencyScope: componentAndDevDependencyTuple.dependencyScope);
|
||||
}
|
||||
else
|
||||
{
|
||||
componentRecorder.RegisterUsage(newTuple.Component, isExplicitReferencedDependency: true, parentComponentId: topLevelComponent.Component.Id, isDevelopmentDependency: componentAndDevDependencyTuple.IsDevelopmentDependency);
|
||||
componentRecorder.RegisterUsage(
|
||||
newTuple.Component,
|
||||
isExplicitReferencedDependency: true,
|
||||
parentComponentId: topLevelComponent.Component.Id,
|
||||
isDevelopmentDependency: componentAndDevDependencyTuple.IsDevelopmentDependency,
|
||||
dependencyScope: componentAndDevDependencyTuple.dependencyScope);
|
||||
}
|
||||
|
||||
tupleStack.Push(newTuple);
|
||||
|
|
|
@ -5,10 +5,12 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using Microsoft.ComponentDetection.Common;
|
||||
using Microsoft.ComponentDetection.Common.DependencyGraph;
|
||||
using Microsoft.ComponentDetection.Common.Telemetry.Records;
|
||||
using Microsoft.ComponentDetection.Contracts;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
using Microsoft.ComponentDetection.Contracts.TypedComponent;
|
||||
using Microsoft.ComponentDetection.Orchestrator.ArgumentSets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Orchestrator.Services.GraphTranslation
|
||||
{
|
||||
|
@ -24,6 +26,8 @@ namespace Microsoft.ComponentDetection.Orchestrator.Services.GraphTranslation
|
|||
|
||||
var mergedComponents = FlattenAndMergeComponents(unmergedComponents);
|
||||
|
||||
LogComponentScopeTelemetry(mergedComponents);
|
||||
|
||||
return new DefaultGraphScanResult
|
||||
{
|
||||
ComponentsFound = mergedComponents.Select(x => ConvertToContract(x)).ToList(),
|
||||
|
@ -35,6 +39,20 @@ namespace Microsoft.ComponentDetection.Orchestrator.Services.GraphTranslation
|
|||
};
|
||||
}
|
||||
|
||||
private void LogComponentScopeTelemetry(List<DetectedComponent> components)
|
||||
{
|
||||
using var record = new DetectedComponentScopeRecord();
|
||||
Parallel.ForEach(components, x =>
|
||||
{
|
||||
if (x.Component.Type.Equals(ComponentType.Maven)
|
||||
&& x.DependencyScope.HasValue
|
||||
&& (x.DependencyScope.Equals(DependencyScope.MavenProvided) || x.DependencyScope.Equals(DependencyScope.MavenSystem)))
|
||||
{
|
||||
record.IncrementProvidedScopeCount();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private IEnumerable<DetectedComponent> GatherSetOfDetectedComponentsUnmerged(IEnumerable<(IComponentDetector detector, ComponentRecorder recorder)> recorderDetectorPairs, DirectoryInfo rootDirectory)
|
||||
{
|
||||
return recorderDetectorPairs
|
||||
|
@ -46,7 +64,7 @@ namespace Microsoft.ComponentDetection.Orchestrator.Services.GraphTranslation
|
|||
var detectedComponents = componentRecorder.GetDetectedComponents();
|
||||
var dependencyGraphsByLocation = componentRecorder.GetDependencyGraphsByLocation();
|
||||
|
||||
// Note that it looks like we are building up detected components functionally, but they are not immutable -- the code is just written
|
||||
// Note that it looks like we are building up detected components functionally, but they are not immutable -- the code is just written
|
||||
// to look like a pipeline.
|
||||
foreach (var component in detectedComponents)
|
||||
{
|
||||
|
@ -62,6 +80,7 @@ namespace Microsoft.ComponentDetection.Orchestrator.Services.GraphTranslation
|
|||
// Calculate roots of the component
|
||||
AddRootsToDetectedComponent(component, dependencyGraph, componentRecorder);
|
||||
component.DevelopmentDependency = MergeDevDependency(component.DevelopmentDependency, dependencyGraph.IsDevelopmentDependency(component.Component.Id));
|
||||
component.DependencyScope = DependencyScopeComparer.GetMergedDependencyScope(component.DependencyScope, dependencyGraph.GetDependencyScope(component.Component.Id));
|
||||
component.DetectedBy = detector;
|
||||
|
||||
// Return in a format that allows us to add the additional files for the components
|
||||
|
@ -130,6 +149,7 @@ namespace Microsoft.ComponentDetection.Orchestrator.Services.GraphTranslation
|
|||
}
|
||||
|
||||
firstComponent.DevelopmentDependency = MergeDevDependency(firstComponent.DevelopmentDependency, nextComponent.DevelopmentDependency);
|
||||
firstComponent.DependencyScope = DependencyScopeComparer.GetMergedDependencyScope(firstComponent.DependencyScope, nextComponent.DependencyScope);
|
||||
|
||||
if (nextComponent.ContainerDetailIds.Count > 0)
|
||||
{
|
||||
|
@ -203,6 +223,7 @@ namespace Microsoft.ComponentDetection.Orchestrator.Services.GraphTranslation
|
|||
{
|
||||
DetectorId = component.DetectedBy.Id,
|
||||
IsDevelopmentDependency = component.DevelopmentDependency,
|
||||
DependencyScope = component.DependencyScope,
|
||||
LocationsFoundAt = component.FilePaths,
|
||||
Component = component.Component,
|
||||
TopLevelReferrers = component.DependencyRoots,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<PackageReference Include="MSTest.TestFramework"/>
|
||||
<PackageReference Include="Moq"/>
|
||||
<PackageReference Include="FluentAssertions"/>
|
||||
<PackageReference Include="Faker.net" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using FluentAssertions;
|
||||
using Microsoft.ComponentDetection.Common.DependencyGraph;
|
||||
using Microsoft.ComponentDetection.Contracts;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
using Microsoft.ComponentDetection.Contracts.TypedComponent;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
|
@ -63,6 +64,20 @@ namespace Microsoft.ComponentDetection.Common.Tests
|
|||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RegisterUsage_DevelopmentDependencyHasValue_componentNodeHasDependencyScope()
|
||||
{
|
||||
var location = "location";
|
||||
var singleFileComponentRecorder = componentRecorder.CreateSingleFileComponentRecorder(location);
|
||||
var detectedComponent = new DetectedComponent(new MavenComponent("org.apache.maven", "maven-artifact", "3.6.1"));
|
||||
|
||||
singleFileComponentRecorder.RegisterUsage(detectedComponent, dependencyScope: DependencyScope.MavenProvided);
|
||||
var dependencyGraph = componentRecorder.GetDependencyGraphForLocation(location);
|
||||
|
||||
dependencyGraph.GetDependencyScope(detectedComponent.Component.Id).Should().NotBeNull();
|
||||
dependencyGraph.GetDependencyScope(detectedComponent.Component.Id).Should().Be(DependencyScope.MavenProvided);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RegisterUsage_DetectedComponentWithNullComponent_ArgumentExceptionIsThrown()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
using FluentAssertions;
|
||||
using FluentAssertions.Primitives;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using Faker;
|
||||
using static Microsoft.ComponentDetection.Common.DependencyScopeComparer;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Common.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Governance/All")]
|
||||
[TestCategory("Governance/ComponentDetection")]
|
||||
public class DependencyScopeComparerTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void GetMergedDependencyScope_returnNull_IfBothNull()
|
||||
{
|
||||
GetMergedDependencyScope(null, null).Should().BeNull();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetMergedDependencyScope_returnSecondIfFirstNulll()
|
||||
{
|
||||
DependencyScope randomDependencyScope = Faker.Enum.Random<DependencyScope>();
|
||||
GetMergedDependencyScope(null, randomDependencyScope)
|
||||
.Should()
|
||||
.Equals(randomDependencyScope);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetMergedDependencyScope_returnFirstIfSecondNulll()
|
||||
{
|
||||
DependencyScope randomDependencyScope = Faker.Enum.Random<DependencyScope>();
|
||||
GetMergedDependencyScope(randomDependencyScope, null)
|
||||
.Should()
|
||||
.Equals(randomDependencyScope);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetMergedDependencyScope_WhenBothNonNull_higherPriorityEnumsReturned()
|
||||
{
|
||||
// compare with compile
|
||||
GetMergedDependencyScope(DependencyScope.MavenRuntime, DependencyScope.MavenCompile).Should().Equals(DependencyScope.MavenCompile);
|
||||
GetMergedDependencyScope(DependencyScope.MavenProvided, DependencyScope.MavenCompile).Should().Equals(DependencyScope.MavenCompile);
|
||||
GetMergedDependencyScope(DependencyScope.MavenSystem, DependencyScope.MavenCompile).Should().Equals(DependencyScope.MavenCompile);
|
||||
GetMergedDependencyScope(DependencyScope.MavenTest, DependencyScope.MavenCompile).Should().Equals(DependencyScope.MavenCompile);
|
||||
|
||||
// compare with runtime
|
||||
GetMergedDependencyScope(DependencyScope.MavenProvided, DependencyScope.MavenRuntime).Should().Equals(DependencyScope.MavenRuntime);
|
||||
GetMergedDependencyScope(DependencyScope.MavenSystem, DependencyScope.MavenRuntime).Should().Equals(DependencyScope.MavenRuntime);
|
||||
GetMergedDependencyScope(DependencyScope.MavenTest, DependencyScope.MavenRuntime).Should().Equals(DependencyScope.MavenRuntime);
|
||||
|
||||
// compare with provided
|
||||
GetMergedDependencyScope(DependencyScope.MavenSystem, DependencyScope.MavenProvided).Should().Equals(DependencyScope.MavenProvided);
|
||||
GetMergedDependencyScope(DependencyScope.MavenTest, DependencyScope.MavenProvided).Should().Equals(DependencyScope.MavenProvided);
|
||||
|
||||
// compare with system
|
||||
GetMergedDependencyScope(DependencyScope.MavenSystem, DependencyScope.MavenTest).Should().Equals(DependencyScope.MavenSystem);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ namespace Microsoft.ComponentDetection.Contracts.Tests
|
|||
Component = new NpmComponent("SampleNpmComponent", "1.2.3"),
|
||||
DetectorId = "NpmDetectorId",
|
||||
IsDevelopmentDependency = true,
|
||||
DependencyScope = DependencyScope.MavenCompile,
|
||||
LocationsFoundAt = new[]
|
||||
{
|
||||
"some/location",
|
||||
|
@ -65,6 +66,7 @@ namespace Microsoft.ComponentDetection.Contracts.Tests
|
|||
var actualDetectedComponent = actual.ComponentsFound.First();
|
||||
actualDetectedComponent.DetectorId.Should().Be("NpmDetectorId");
|
||||
actualDetectedComponent.IsDevelopmentDependency.Should().Be(true);
|
||||
actualDetectedComponent.DependencyScope.Should().Be(DependencyScope.MavenCompile);
|
||||
actualDetectedComponent.LocationsFoundAt.Contains("some/location").Should().Be(true);
|
||||
|
||||
var npmComponent = actualDetectedComponent.Component as NpmComponent;
|
||||
|
@ -95,6 +97,7 @@ namespace Microsoft.ComponentDetection.Contracts.Tests
|
|||
|
||||
foundComponent.Value<string>("detectorId").Should().Be("NpmDetectorId");
|
||||
foundComponent.Value<bool>("isDevelopmentDependency").Should().Be(true);
|
||||
foundComponent.Value<string>("dependencyScope").Should().Be("MavenCompile");
|
||||
foundComponent["locationsFoundAt"].First().Value<string>().Should().Be("some/location");
|
||||
foundComponent["component"].Value<string>("type").Should().Be("Npm");
|
||||
foundComponent["component"].Value<string>("name").Should().Be("SampleNpmComponent");
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.ComponentDetection.Detectors.Maven;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using static Microsoft.ComponentDetection.Detectors.Maven.MavenParsingUtilities;
|
||||
using Microsoft.ComponentDetection.Contracts.TypedComponent;
|
||||
using FluentAssertions.Collections;
|
||||
using Microsoft.ComponentDetection.Contracts.BcdeModels;
|
||||
using Microsoft.ComponentDetection.Contracts;
|
||||
|
||||
namespace Microsoft.ComponentDetection.Detectors.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Governance/All")]
|
||||
[TestCategory("Governance/ComponentDetection")]
|
||||
public class MavenParsingUtilitiesTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void GenerateDetectedComponentAndIsDeveDependencyAndDependencyScope_HappyPath()
|
||||
{
|
||||
var componentAndMetaData =
|
||||
GenerateDetectedComponentAndMetadataFromMavenString("org.apache.maven:maven-artifact:jar:3.6.1-SNAPSHOT:provided");
|
||||
|
||||
Assert.IsNotNull(componentAndMetaData);
|
||||
Assert.IsNotNull(componentAndMetaData.Component);
|
||||
Assert.IsNotNull(componentAndMetaData.IsDevelopmentDependency);
|
||||
Assert.IsNotNull(componentAndMetaData.dependencyScope);
|
||||
|
||||
var actualComponent = (MavenComponent)componentAndMetaData.Component.Component;
|
||||
Assert.IsInstanceOfType(actualComponent, typeof(MavenComponent));
|
||||
|
||||
var expectedComponent = new MavenComponent("org.apache.maven", "maven-artifact", "3.6.1-SNAPSHOT");
|
||||
|
||||
Assert.AreEqual(expectedComponent.ArtifactId, actualComponent.ArtifactId);
|
||||
Assert.AreEqual(expectedComponent.GroupId, actualComponent.GroupId);
|
||||
Assert.AreEqual(expectedComponent.Version, actualComponent.Version);
|
||||
|
||||
Assert.IsFalse(componentAndMetaData.IsDevelopmentDependency);
|
||||
Assert.AreEqual(DependencyScope.MavenProvided, componentAndMetaData.dependencyScope);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateDetectedComponentAndIsDeveDependencyAndDependencyScope_DefaultScopeCompile()
|
||||
{
|
||||
var componentAndMetaData =
|
||||
GenerateDetectedComponentAndMetadataFromMavenString("org.apache.maven:maven-artifact:jar:3.6.1-SNAPSHOT");
|
||||
|
||||
Assert.IsNotNull(componentAndMetaData);
|
||||
Assert.IsNotNull(componentAndMetaData.dependencyScope);
|
||||
|
||||
var actualComponent = (MavenComponent)componentAndMetaData.Component.Component;
|
||||
Assert.IsInstanceOfType(actualComponent, typeof(MavenComponent));
|
||||
Assert.AreEqual(DependencyScope.MavenCompile, componentAndMetaData.dependencyScope);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateDetectedComponentAndIsDeveDependencyAndDependencyScope_DevelopmentDependencyTrue()
|
||||
{
|
||||
var componentAndMetaData =
|
||||
GenerateDetectedComponentAndMetadataFromMavenString("org.apache.maven:maven-artifact:jar:3.6.1-SNAPSHOT:test");
|
||||
|
||||
Assert.IsNotNull(componentAndMetaData);
|
||||
Assert.IsNotNull(componentAndMetaData.IsDevelopmentDependency);
|
||||
|
||||
var actualComponent = (MavenComponent)componentAndMetaData.Component.Component;
|
||||
Assert.IsInstanceOfType(actualComponent, typeof(MavenComponent));
|
||||
Assert.IsTrue(componentAndMetaData.IsDevelopmentDependency);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GenerateDetectedComponentAndIsDeveDependencyAndDependencyScope_InvalidScope()
|
||||
{
|
||||
var ex = Assert.ThrowsException<InvalidOperationException>(
|
||||
() => GenerateDetectedComponentAndMetadataFromMavenString("org.apache.maven:maven-artifact:jar:3.6.1-SNAPSHOT:invalidScope"));
|
||||
Assert.IsTrue(ex.Message.Contains("invalid scope", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,15 +56,15 @@ namespace Microsoft.ComponentDetection.Detectors.Tests
|
|||
|
||||
var dependencyGraph = componentRecorder.GetDependencyGraphsByLocation()[pomfileLocation];
|
||||
|
||||
var topLevelComponentTuple = MavenParsingUtilities.GenerateDetectedComponentFromMavenString("org.apache.maven:maven-compat:jar:3.6.1-SNAPSHOT");
|
||||
var topLevelComponent = topLevelComponentTuple.Component;
|
||||
var mavenCoreTuple = MavenParsingUtilities.GenerateDetectedComponentFromMavenString("org.apache.maven:maven-core:jar:3.6.1-SNAPSHOT:compile");
|
||||
var topLevelComponentInfo = MavenParsingUtilities.GenerateDetectedComponentAndMetadataFromMavenString("org.apache.maven:maven-compat:jar:3.6.1-SNAPSHOT");
|
||||
var topLevelComponent = topLevelComponentInfo.Component;
|
||||
var mavenCoreTuple = MavenParsingUtilities.GenerateDetectedComponentAndMetadataFromMavenString("org.apache.maven:maven-core:jar:3.6.1-SNAPSHOT:compile");
|
||||
var mavenCore = mavenCoreTuple.Component;
|
||||
var guiceTuple = MavenParsingUtilities.GenerateDetectedComponentFromMavenString("com.google.inject:guice:jar:no_aop:4.2.1:compile");
|
||||
var guiceTuple = MavenParsingUtilities.GenerateDetectedComponentAndMetadataFromMavenString("com.google.inject:guice:jar:no_aop:4.2.1:compile");
|
||||
var guice = guiceTuple.Component;
|
||||
var guavaTuple = MavenParsingUtilities.GenerateDetectedComponentFromMavenString("com.google.guava:guava:jar:25.1-android:compile");
|
||||
var guavaTuple = MavenParsingUtilities.GenerateDetectedComponentAndMetadataFromMavenString("com.google.guava:guava:jar:25.1-android:compile");
|
||||
var guava = guavaTuple.Component;
|
||||
var animalSnifferAnnotationsTuple = MavenParsingUtilities.GenerateDetectedComponentFromMavenString("org.codehaus.mojo:animal-sniffer-annotations:jar:1.14:compile");
|
||||
var animalSnifferAnnotationsTuple = MavenParsingUtilities.GenerateDetectedComponentAndMetadataFromMavenString("org.codehaus.mojo:animal-sniffer-annotations:jar:1.14:compile");
|
||||
var animalSnifferAnnotations = animalSnifferAnnotationsTuple.Component;
|
||||
|
||||
var topLevelComponentDependencies = dependencyGraph.GetDependenciesForComponent(topLevelComponent.Component.Id);
|
||||
|
|
Загрузка…
Ссылка в новой задаче