public void BeforeAddOrUpdate_WhenUnresolvedAndExistsResolvedInSnapshot_ShouldReturnNull() { var unresolvedDependency = new TestDependency { Id = "dependency", Resolved = false }; var resolvedDependency = new TestDependency { Id = "dependency", Resolved = true }; var dependencyById = new Dictionary <(string ProviderType, string ModelId), IDependency> { { (resolvedDependency.ProviderType, resolvedDependency.Id), resolvedDependency } }; var context = new AddDependencyContext(dependencyById); var filter = new UnresolvedDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( unresolvedDependency, null !, null, context); // Dependency rejected Assert.Null(context.GetResult(filter)); // Nothing else changed Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenUnresolvedAndNotExistsResolvedInSnapshot_ShouldReturnDependency() { var unresolvedDependency = new TestDependency { Id = "dependency", Resolved = false }; var dependencyById = new Dictionary <string, IDependency>(); var context = new AddDependencyContext(dependencyById); var filter = new UnresolvedDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( null !, unresolvedDependency, null !, null, context); // Dependency accepted unchanged Assert.Same(unresolvedDependency, context.GetResult(filter)); // Nothing else changed Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenResolved_ShouldReturnDependency() { var resolvedDependency = new TestDependency { Id = "dependency", Resolved = true }; var worldBuilder = ImmutableDictionary <string, IDependency> .Empty.ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new UnresolvedDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( null, resolvedDependency, null, null, context); // Dependency accepted unchanged Assert.Same(resolvedDependency, context.GetResult(filter)); // Nothing else changed Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenUnresolvedAndExistsResolvedInSnapshot_ShouldReturnNull() { var unresolvedDependency = new TestDependency { Id = "dependency", Resolved = false }; var resolvedDependency = new TestDependency { Id = "dependency", Resolved = true }; var worldBuilder = new IDependency[] { resolvedDependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new UnresolvedDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( null, unresolvedDependency, null, null, context); // Dependency rejected Assert.Null(context.GetResult(filter)); // Nothing else changed Assert.False(context.Changed); }
public void BeforeAddOrUpdate( IDependency dependency, AddDependencyContext context) { (string ProviderType, string Id)key = (dependency.ProviderType, dependency.Id); if (_beforeAdd.TryGetValue(key, out (FilterAction Action, IDependency? Dependency)info)) { if (info.Action == FilterAction.Reject) { context.Reject(); if (info.Dependency != null) { context.AddOrUpdate(info.Dependency); } } else if (info.Action == FilterAction.Accept) { context.Accept(info.Dependency ?? dependency); } else { throw new NotSupportedException(); } _beforeAdd.Remove(key); } else { throw new ArgumentException("Unexpected dependency: " + key); } }
public void BeforeAddOrUpdate_WhenDependencyNotRecognized_ShouldDoNothing() { var acceptable = new TestDependency { Id = "dependency1", TopLevel = true, Resolved = true, Flags = DependencyTreeFlags.ProjectNodeFlags }; AssertNoChange(new TestDependency { ClonePropertiesFrom = acceptable, TopLevel = false }); AssertNoChange(new TestDependency { ClonePropertiesFrom = acceptable, Resolved = false }); AssertNoChange(new TestDependency { ClonePropertiesFrom = acceptable, Flags = ProjectTreeFlags.Empty }); AssertNoChange(new TestDependency { ClonePropertiesFrom = acceptable, Flags = DependencyTreeFlags.ProjectNodeFlags.Union(DependencyTreeFlags.SharedProjectFlags) }); return; void AssertNoChange(IDependency dependency) { var aggregateSnapshotProvider = IAggregateDependenciesSnapshotProviderFactory.Create(); var worldBuilder = new[] { dependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new UnsupportedProjectsSnapshotFilter(aggregateSnapshotProvider); filter.BeforeAddOrUpdate( null, dependency, null, null, context); // Accepts unchanged dependency Assert.Same(dependency, context.GetResult(filter)); // No other changes made Assert.False(context.Changed); } }
public void BeforeAddOrUpdate_WhenNeedToApplyImplicit_ShouldSetProperties() { const string providerType = "providerType"; const string projectItemSpec = "projectItemSpec"; var implicitIcon = KnownMonikers.Abbreviation; var dependency = new TestDependency { Id = "dependency1", ProviderType = providerType, Implicit = false, Resolved = true, Flags = DependencyTreeFlags.GenericResolvedDependencyFlags, OriginalItemSpec = projectItemSpec, IconSet = new DependencyIconSet(KnownMonikers.Reference, KnownMonikers.Reference, KnownMonikers.Reference, KnownMonikers.Reference) }; var dependencyById = new Dictionary <(string ProviderType, string ModelId), IDependency> { { (dependency.ProviderType, dependency.Id), dependency } }; var context = new AddDependencyContext(dependencyById); var filter = new ImplicitDependenciesSnapshotFilter(); var subTreeProvider = IProjectDependenciesSubTreeProviderFactory.ImplementInternal( providerType: providerType, implicitIcon: implicitIcon); filter.BeforeAddOrUpdate( dependency, new Dictionary <string, IProjectDependenciesSubTreeProvider> { { providerType, subTreeProvider } }, ImmutableHashSet <string> .Empty, context); var acceptedDependency = context.GetResult(filter); // Returns changed dependency Assert.NotNull(acceptedDependency); Assert.NotSame(dependency, acceptedDependency); DependencyAssert.Equal( new TestDependency { ClonePropertiesFrom = dependency, Implicit = true, IconSet = new DependencyIconSet( implicitIcon, implicitIcon, KnownMonikers.Reference, KnownMonikers.Reference), Flags = DependencyTreeFlags.GenericResolvedDependencyFlags.Except(DependencyTreeFlags.SupportsRemove) }, acceptedDependency !); // No other changes made Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenNeedToApplyImplicit_ShouldSetProperties() { const string providerType = "providerType"; const string projectItemSpec = "projectItemSpec"; var implicitIcon = KnownMonikers.Abbreviation; var dependency = new TestDependency { Id = "dependency1", ProviderType = providerType, TopLevel = true, Implicit = false, Resolved = true, Flags = DependencyTreeFlags.GenericDependencyFlags, OriginalItemSpec = projectItemSpec, IconSet = new DependencyIconSet(KnownMonikers.Reference, KnownMonikers.Reference, KnownMonikers.Reference, KnownMonikers.Reference) }; var worldBuilder = new IDependency[] { dependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new ImplicitTopLevelDependenciesSnapshotFilter(); var subTreeProvider = IProjectDependenciesSubTreeProviderFactory.ImplementInternal( providerType: providerType, implicitIcon: implicitIcon); filter.BeforeAddOrUpdate( null, null, dependency, new Dictionary <string, IProjectDependenciesSubTreeProvider> { { providerType, subTreeProvider } }, ImmutableHashSet <string> .Empty, context); var acceptedDependency = context.GetResult(filter); // Returns changed dependency Assert.NotNull(acceptedDependency); Assert.NotSame(dependency, acceptedDependency); acceptedDependency.AssertEqualTo( new TestDependency { ClonePropertiesFrom = dependency, Implicit = true, IconSet = new DependencyIconSet( implicitIcon, implicitIcon, KnownMonikers.Reference, KnownMonikers.Reference) }); // No other changes made Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenThereIsMatchingDependencies_ShouldUpdateCaptionForAll() { // Both top level // Same provider type // Same captions // -> Changes caption for both to match alias const string providerType = "provider"; const string caption = "caption1"; var dependency = new TestDependency { Id = "dependency1", Alias = "dependency1 (dependency1ItemSpec)", ProviderType = providerType, Caption = caption, TopLevel = true }; var otherDependency = new TestDependency { ClonePropertiesFrom = dependency, // clone, with changes Id = "dependency2", Alias = "dependency2 (dependency2ItemSpec)" }; var worldBuilder = new IDependency[] { dependency, otherDependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new DuplicatedDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( null, null, dependency, null, null, context); // The context changed, beyond just the filtered dependency Assert.True(context.Changed); // The filtered dependency had its caption changed to its alias var dependencyAfter = context.GetResult(filter); dependencyAfter.AssertEqualTo( new TestDependency { ClonePropertiesFrom = dependency, Caption = dependency.Alias }); // The other dependency had its caption changed to its alias Assert.True(context.TryGetDependency(otherDependency.Id, out IDependency otherDependencyAfter)); otherDependencyAfter.AssertEqualTo( new TestDependency { ClonePropertiesFrom = otherDependency, Caption = otherDependency.Alias }); }
public void BeforeAddOrUpdate_WhenThereIsMatchingDependencyWithAliasApplied_ShouldUpdateCaptionForCurrentDependency() { // Both top level // Same provider type // Duplicate caption, though with parenthesized text after one instance // -> Changes caption of non-parenthesized const string providerType = "provider"; const string caption = "caption"; var dependency = new TestDependency { Id = "id1", OriginalItemSpec = "originalItemSpec1", ProviderType = providerType, Caption = caption, TopLevel = true }; var otherDependency = new TestDependency { ClonePropertiesFrom = dependency, Id = "id2", OriginalItemSpec = "originalItemSpec2", Caption = $"{caption} (originalItemSpec2)" // caption already includes alias }; var worldBuilder = new IDependency[] { dependency, otherDependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new DeduplicateCaptionsSnapshotFilter(); filter.BeforeAddOrUpdate( null !, dependency, null !, null, context); // The context was unchanged, beyond the filtered dependency Assert.False(context.Changed); // The filtered dependency had its caption changed to its alias var dependencyAfter = context.GetResult(filter); DependencyAssert.Equal(new TestDependency { ClonePropertiesFrom = dependency, Caption = "caption (originalItemSpec1)" }, dependencyAfter !); // The other dependency had its caption changed to its alias Assert.True(context.TryGetDependency(otherDependency.Id, out IDependency otherDependencyAfter)); DependencyAssert.Equal(new TestDependency { ClonePropertiesFrom = otherDependency, Caption = "caption (originalItemSpec2)" }, otherDependencyAfter); }
public void BeforeAddOrUpdate_WhenThereIsMatchingDependencies_ShouldUpdateCaptionForAll() { // Same provider type // Same captions // -> Changes caption for both to match alias const string providerType = "provider"; const string caption = "caption"; var dependency = new TestDependency { Id = "id1", OriginalItemSpec = "originalItemSpec1", ProviderType = providerType, Caption = caption }; var otherDependency = new TestDependency { ClonePropertiesFrom = dependency, // clone, with changes Id = "id2", OriginalItemSpec = "originalItemSpec2" }; var dependencyById = new IDependency[] { dependency, otherDependency }.ToDictionary(d => d.Id); var context = new AddDependencyContext(dependencyById); var filter = new DeduplicateCaptionsSnapshotFilter(); filter.BeforeAddOrUpdate( null !, dependency, null !, null, context); // The context changed, beyond just the filtered dependency Assert.True(context.Changed); // The filtered dependency had its caption changed to its alias var dependencyAfter = context.GetResult(filter); DependencyAssert.Equal(new TestDependency { ClonePropertiesFrom = dependency, Caption = "caption (originalItemSpec1)" }, dependencyAfter !); // The other dependency had its caption changed to its alias Assert.True(context.TryGetDependency(otherDependency.Id, out IDependency otherDependencyAfter)); DependencyAssert.Equal(new TestDependency { ClonePropertiesFrom = otherDependency, Caption = "caption (originalItemSpec2)" }, otherDependencyAfter); }
public void BeforeAddOrUpdate_WhenProjectSnapshotFoundAndHasUnresolvedDependencies_ShouldMakeUnresolved() { const string projectPath = @"c:\project\project.csproj"; var targetFramework = ITargetFrameworkFactory.Implement(moniker: "tfm1"); var targetedSnapshot = ITargetedDependenciesSnapshotFactory.Implement(hasUnresolvedDependency: true); var targets = new Dictionary <ITargetFramework, ITargetedDependenciesSnapshot> { { targetFramework, targetedSnapshot } }; var snapshot = IDependenciesSnapshotFactory.Implement(targets: targets); var snapshotProvider = IDependenciesSnapshotProviderFactory.Implement(currentSnapshot: snapshot); var aggregateSnapshotProvider = new Mock <IAggregateDependenciesSnapshotProvider>(MockBehavior.Strict); aggregateSnapshotProvider.Setup(x => x.GetSnapshotProvider(projectPath)).Returns(snapshotProvider); var targetFrameworkProvider = ITargetFrameworkProviderFactory.Implement(getNearestFramework: targetFramework); var dependency = new TestDependency { Id = "dependency1", TopLevel = true, Resolved = true, Flags = DependencyTreeFlags.ProjectNodeFlags.Union(DependencyTreeFlags.ResolvedFlags), TargetFramework = targetFramework, FullPath = projectPath }; var worldBuilder = ImmutableDictionary <string, IDependency> .Empty.ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new UnsupportedProjectsSnapshotFilter(aggregateSnapshotProvider.Object, targetFrameworkProvider); filter.BeforeAddOrUpdate( null, null, dependency, null, null, context); // Accepts unresolved version var acceptedDependency = context.GetResult(filter); acceptedDependency.AssertEqualTo( dependency.ToUnresolved(ProjectReference.SchemaName)); // No other changes made Assert.False(context.Changed); aggregateSnapshotProvider.VerifyAll(); }
public void BeforeAddOrUpdate_WhenSdk_ShouldFindMatchingPackageAndSetProperties() { var dependencyIDs = ImmutableList.Create("id1", "id2"); var targetFramework = new TargetFramework("tfm"); const string sdkName = "sdkName"; var sdkDependency = new TestDependency { Id = "dependency1Id", Name = sdkName, TopLevel = true, Resolved = false, Flags = DependencyTreeFlags.SdkSubTreeNodeFlags }; var packageDependency = new TestDependency { Id = Dependency.GetID(targetFramework, PackageRuleHandler.ProviderTypeString, sdkName), Resolved = true, DependencyIDs = dependencyIDs, Flags = DependencyTreeFlags.PackageNodeFlags }; var worldBuilder = new IDependency[] { sdkDependency, packageDependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new SdkAndPackagesDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( null, targetFramework, sdkDependency, null, null, context); var acceptedDependency = context.GetResult(filter); // Dependency should be accepted, but converted to resolved state Assert.NotNull(acceptedDependency); Assert.NotSame(sdkDependency, acceptedDependency); acceptedDependency.AssertEqualTo( sdkDependency.ToResolved( schemaName: ResolvedSdkReference.SchemaName, dependencyIDs: dependencyIDs)); // No changes other than the filtered dependency Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenPackage_ShouldFindMatchingSdkAndSetProperties() { var dependencyIDs = ImmutableList.Create("id1", "id2"); var targetFramework = new TargetFramework("tfm"); const string packageName = "packageName"; var sdkDependency = new TestDependency { Id = Dependency.GetID(targetFramework, SdkRuleHandler.ProviderTypeString, packageName), TopLevel = false, Resolved = true, Flags = DependencyTreeFlags.PackageNodeFlags.Union(DependencyTreeFlags.UnresolvedFlags) // to see if unresolved is fixed }; var packageDependency = new TestDependency { Id = "packageId", Name = packageName, Flags = DependencyTreeFlags.PackageNodeFlags, TopLevel = true, Resolved = true, DependencyIDs = dependencyIDs }; var worldBuilder = new IDependency[] { packageDependency, sdkDependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new SdkAndPackagesDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( null, targetFramework, packageDependency, null, null, context); // Accepts unchanged dependency Assert.Same(packageDependency, context.GetResult(filter)); // Other changes made Assert.True(context.Changed); Assert.True(context.TryGetDependency(sdkDependency.Id, out IDependency sdkDependencyAfter)); sdkDependencyAfter.AssertEqualTo( sdkDependency.ToResolved( schemaName: ResolvedSdkReference.SchemaName, dependencyIDs: dependencyIDs)); }
public void BeforeAddOrUpdate_WhenThereIsMatchingDependency_WithSubstringCaption() { // Both top level // Same provider type // Duplicate caption prefix // -> No change const string providerType = "provider"; const string caption = "caption"; var dependency = new TestDependency { Id = "dependency1", ProviderType = providerType, Caption = caption, TopLevel = true }; var otherDependency = new TestDependency { ClonePropertiesFrom = dependency, Id = "dependency2", OriginalItemSpec = "dependency2ItemSpec", Caption = $"{caption}X" // identical caption prefix }; // TODO test a longer suffix here -- looks like the implementation might not handle it correctly var worldBuilder = new IDependency[] { dependency, otherDependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new DuplicatedDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( null, null, dependency, null, null, context); // Accepts unchanged dependency Assert.Same(dependency, context.GetResult(filter)); // No other changes made Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenPackage_ShouldFindMatchingSdkAndSetProperties() { var targetFramework = new TargetFramework("tfm"); const string packageName = "packageName"; var sdkDependency = new TestDependency { Id = Dependency.GetID(targetFramework, SdkRuleHandler.ProviderTypeString, packageName), Resolved = true, Flags = DependencyTreeFlags.PackageDependency.Union(DependencyTreeFlags.Unresolved) // to see if unresolved is fixed }; var packageDependency = new TestDependency { Id = "packageId", Name = packageName, Flags = DependencyTreeFlags.PackageDependency, Resolved = true }; var builder = new IDependency[] { packageDependency, sdkDependency }.ToDictionary(d => d.Id); var context = new AddDependencyContext(builder); var filter = new SdkAndPackagesDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( targetFramework, packageDependency, null !, null, context); // Accepts unchanged dependency Assert.Same(packageDependency, context.GetResult(filter)); // Other changes made Assert.True(context.Changed); Assert.True(context.TryGetDependency(sdkDependency.Id, out IDependency sdkDependencyAfter)); DependencyAssert.Equal( sdkDependency.ToResolved( schemaName: ResolvedSdkReference.SchemaName), sdkDependencyAfter); }
public void BeforeAddOrUpdate_NoDuplicate_ShouldNotUpdateCaption() { // Both top level // Same provider type // Different captions // -> No change const string providerType = "provider"; var dependency = new TestDependency { Id = "dependency1", Caption = "caption1", ProviderType = providerType, TopLevel = true }; var otherDependency = new TestDependency { Id = "dependency2", Caption = "caption2", ProviderType = providerType, TopLevel = true }; var worldBuilder = new IDependency[] { dependency, otherDependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new DuplicatedDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( null, null, dependency, null, null, context); // Accepts unchanged dependency Assert.Same(dependency, context.GetResult(filter)); // No other changes made Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenSdk_ShouldFindMatchingPackageAndSetProperties() { const string sdkName = "sdkName"; var sdkDependency = new TestDependency { Id = sdkName, ProviderType = SdkRuleHandler.ProviderTypeString, Resolved = false, Flags = DependencyTreeFlags.SdkDependency }; var packageDependency = new TestDependency { Id = sdkName, ProviderType = PackageRuleHandler.ProviderTypeString, Resolved = true, Flags = DependencyTreeFlags.PackageDependency }; var builder = new IDependency[] { sdkDependency, packageDependency }.ToDictionary(IDependencyExtensions.GetDependencyId); var context = new AddDependencyContext(builder); var filter = new SdkAndPackagesDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( sdkDependency, null !, null, context); var acceptedDependency = context.GetResult(filter); // Dependency should be accepted, but converted to resolved state Assert.NotNull(acceptedDependency); Assert.NotSame(sdkDependency, acceptedDependency); DependencyAssert.Equal( sdkDependency.ToResolved(schemaName: ResolvedSdkReference.SchemaName, diagnosticLevel: DiagnosticLevel.None), acceptedDependency !); // No changes other than the filtered dependency Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenProjectSnapshotFoundAndNoUnresolvedDependencies_ShouldDoNothing() { const string projectPath = @"c:\project\project.csproj"; var targetFramework = ITargetFrameworkFactory.Implement(moniker: "tfm1"); var targetedSnapshot = ITargetedDependenciesSnapshotFactory.Implement(hasUnresolvedDependency: false); var dependency = new TestDependency { Id = "dependency1", TopLevel = true, Resolved = true, Flags = DependencyTreeFlags.ProjectNodeFlags.Union(DependencyTreeFlags.ResolvedFlags), FullPath = projectPath, TargetFramework = targetFramework }; var aggregateSnapshotProvider = new Mock <IAggregateDependenciesSnapshotProvider>(MockBehavior.Strict); aggregateSnapshotProvider.Setup(x => x.GetSnapshot(dependency)).Returns(targetedSnapshot); var worldBuilder = ImmutableDictionary <string, IDependency> .Empty.ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new UnsupportedProjectsSnapshotFilter(aggregateSnapshotProvider.Object); filter.BeforeAddOrUpdate( null, null, dependency, null, null, context); // Accepts unchanged dependency Assert.Same(dependency, context.GetResult(filter)); // No other changes made Assert.False(context.Changed); aggregateSnapshotProvider.VerifyAll(); }
public void BeforeAddOrUpdate_WhenPackage_ShouldFindMatchingSdkAndSetProperties() { const string packageName = "packageName"; var sdkDependency = new TestDependency { Id = packageName, ProviderType = SdkRuleHandler.ProviderTypeString, Resolved = true, Flags = DependencyTreeFlags.PackageDependency.Union(ProjectTreeFlags.BrokenReference) // to see if unresolved is fixed }; var packageDependency = new TestDependency { Id = packageName, ProviderType = PackageRuleHandler.ProviderTypeString, Flags = DependencyTreeFlags.PackageDependency, Resolved = true }; var builder = new IDependency[] { packageDependency, sdkDependency }.ToDictionary(IDependencyExtensions.GetDependencyId); var context = new AddDependencyContext(builder); var filter = new SdkAndPackagesDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( packageDependency, null !, null, context); // Accepts unchanged dependency Assert.Same(packageDependency, context.GetResult(filter)); // Other changes made Assert.True(context.Changed); Assert.True(context.TryGetDependency(sdkDependency.GetDependencyId(), out IDependency sdkDependencyAfter)); DependencyAssert.Equal( sdkDependency.ToResolved(schemaName: ResolvedSdkReference.SchemaName, diagnosticLevel: DiagnosticLevel.None), sdkDependencyAfter); }
public void BeforeAddOrUpdate_WhenSdkAndPackageUnresolved_ShouldDoNothing() { var targetFramework = new TargetFramework("tfm"); const string sdkName = "sdkName"; var sdkDependency = new TestDependency { Id = "dependency1", Name = sdkName, TopLevel = false, Resolved = true, Flags = DependencyTreeFlags.SdkSubTreeNodeFlags }; var packageDependency = new TestDependency { Id = Dependency.GetID(targetFramework, PackageRuleHandler.ProviderTypeString, sdkName), Resolved = false, Flags = DependencyTreeFlags.PackageNodeFlags }; var worldBuilder = new IDependency[] { sdkDependency, packageDependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new SdkAndPackagesDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( null, targetFramework, sdkDependency, null, null, context); // Accepts unchanged dependency Assert.Same(sdkDependency, context.GetResult(filter)); // No other changes made Assert.False(context.Changed); }
private protected void VerifyUnchangedOnAdd(IDependency dependency, IImmutableSet <string> projectItemSpecs = null) { var worldBuilder = new[] { dependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = CreateFilter(); filter.BeforeAddOrUpdate( null, dependency, null, projectItemSpecs, context); // Accepts unchanged dependency Assert.Same(dependency, context.GetResult(filter)); // No other changes made Assert.False(context.Changed); }
public void BeforeAddOrUpdate_NoDuplicate_ShouldNotUpdateCaption() { // Same provider type // Different captions // -> No change const string providerType = "provider"; var dependency = new TestDependency { Id = "dependency1", Caption = "caption1", ProviderType = providerType }; var otherDependency = new TestDependency { Id = "dependency2", Caption = "caption2", ProviderType = providerType }; var dependencyById = new IDependency[] { dependency, otherDependency }.ToDictionary(IDependencyExtensions.GetDependencyId); var context = new AddDependencyContext(dependencyById); var filter = new DeduplicateCaptionsSnapshotFilter(); filter.BeforeAddOrUpdate( dependency, null !, null, context); // Accepts unchanged dependency Assert.Same(dependency, context.GetResult(filter)); // No other changes made Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenSdkAndPackageUnresolved_ShouldDoNothing() { const string sdkName = "sdkName"; var sdkDependency = new TestDependency { Id = "dependency1", ProviderType = SdkRuleHandler.ProviderTypeString, OriginalItemSpec = sdkName, Resolved = true, Flags = DependencyTreeFlags.SdkDependency }; var packageDependency = new TestDependency { Id = sdkName, ProviderType = PackageRuleHandler.ProviderTypeString, Resolved = false, Flags = DependencyTreeFlags.PackageDependency }; var builder = new IDependency[] { sdkDependency, packageDependency }.ToDictionary(IDependencyExtensions.GetDependencyId); var context = new AddDependencyContext(builder); var filter = new SdkAndPackagesDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( sdkDependency, null !, null, context); // Accepts unchanged dependency Assert.Same(sdkDependency, context.GetResult(filter)); // No other changes made Assert.False(context.Changed); }
public void BeforeAddOrUpdate_WhenResolved_ShouldReturnDependency() { var resolvedDependency = new TestDependency { Id = "dependency", Resolved = true }; var dependencyById = new Dictionary <DependencyId, IDependency>(); var context = new AddDependencyContext(dependencyById); var filter = new UnresolvedDependenciesSnapshotFilter(); filter.BeforeAddOrUpdate( resolvedDependency, context); // Dependency accepted unchanged Assert.Same(resolvedDependency, context.GetResult(filter)); // Nothing else changed Assert.False(context.Changed); }
private protected void VerifyUnchangedOnAdd(IDependency dependency, IImmutableSet <string>?projectItemSpecs = null) { var dependencyById = new Dictionary <(string ProviderType, string ModelId), IDependency> { { (dependency.ProviderType, dependency.Id), dependency } }; var context = new AddDependencyContext(dependencyById); var filter = CreateFilter(); filter.BeforeAddOrUpdate( dependency, null !, projectItemSpecs, context); // Accepts unchanged dependency Assert.Same(dependency, context.GetResult(filter)); // No other changes made Assert.False(context.Changed); }
static void AssertNoChange(IDependency dependency) { var aggregateSnapshotProvider = IAggregateDependenciesSnapshotProviderFactory.Create(); var worldBuilder = new[] { dependency }.ToImmutableDictionary(d => d.Id).ToBuilder(); var context = new AddDependencyContext(worldBuilder); var filter = new UnresolvedProjectReferenceSnapshotFilter(aggregateSnapshotProvider); filter.BeforeAddOrUpdate( null !, dependency, null !, null, context); // Accepts unchanged dependency Assert.Same(dependency, context.GetResult(filter)); // No other changes made Assert.False(context.Changed); }
/// <summary> /// Applies changes to <paramref name="previousSnapshot"/> and produces a new snapshot if required. /// If no changes are made, <paramref name="previousSnapshot"/> is returned unmodified. /// </summary> /// <returns>An updated snapshot, or <paramref name="previousSnapshot"/> if no changes occurred.</returns> public static TargetedDependenciesSnapshot FromChanges( TargetedDependenciesSnapshot previousSnapshot, IDependenciesChanges?changes, IProjectCatalogSnapshot?catalogs, ImmutableArray <IDependenciesSnapshotFilter> snapshotFilters) { Requires.NotNull(previousSnapshot, nameof(previousSnapshot)); Requires.Argument(!snapshotFilters.IsDefault, nameof(snapshotFilters), "Cannot be default."); bool anyChanges = false; TargetFramework targetFramework = previousSnapshot.TargetFramework; var dependencyById = previousSnapshot.Dependencies.ToDictionary(IDependencyExtensions.GetDependencyId); if (changes != null && changes.RemovedNodes.Count != 0) { foreach (IDependencyModel removed in changes.RemovedNodes) { dependencyById.Remove(removed.GetDependencyId()); } anyChanges = true; } if (changes != null && changes.AddedNodes.Count != 0) { var context = new AddDependencyContext(dependencyById); foreach (IDependencyModel added in changes.AddedNodes) { #pragma warning disable CS0618 // Type or member is obsolete // NOTE we still need to check this in case extensions (eg. WebTools) provide us with top level items that need to be filtered out if (!added.TopLevel) { continue; } #pragma warning restore CS0618 // Type or member is obsolete Add(context, added); } } // Also factor in any changes to path/framework/catalogs anyChanges = anyChanges || !targetFramework.Equals(previousSnapshot.TargetFramework) || !Equals(catalogs, previousSnapshot.Catalogs); if (anyChanges) { return(new TargetedDependenciesSnapshot( targetFramework, catalogs, dependencyById.ToImmutableValueArray())); } return(previousSnapshot); void Add(AddDependencyContext context, IDependencyModel dependencyModel) { // Create the unfiltered dependency IDependency?dependency = new Dependency(dependencyModel); context.Reset(); foreach (IDependenciesSnapshotFilter filter in snapshotFilters) { filter.BeforeAddOrUpdate( dependency, context); dependency = context.GetResult(filter); if (dependency == null) { break; } } if (dependency != null) { // A dependency was accepted DependencyId id = dependencyModel.GetDependencyId(); dependencyById.Remove(id); dependencyById.Add(id, dependency); anyChanges = true; } else { // Even though the dependency was rejected, it's possible that filters made // changes to other dependencies. anyChanges |= context.Changed; } } }
/// <summary> /// Applies changes to <paramref name="previousSnapshot"/> and produces a new snapshot if required. /// If no changes are made, <paramref name="previousSnapshot"/> is returned unmodified. /// </summary> /// <returns>An updated snapshot, or <paramref name="previousSnapshot"/> if no changes occured.</returns> public static TargetedDependenciesSnapshot FromChanges( string projectPath, TargetedDependenciesSnapshot previousSnapshot, IDependenciesChanges changes, IProjectCatalogSnapshot?catalogs, ImmutableArray <IDependenciesSnapshotFilter> snapshotFilters, IReadOnlyDictionary <string, IProjectDependenciesSubTreeProvider> subTreeProviderByProviderType, IImmutableSet <string>?projectItemSpecs) { Requires.NotNullOrWhiteSpace(projectPath, nameof(projectPath)); Requires.NotNull(previousSnapshot, nameof(previousSnapshot)); Requires.NotNull(changes, nameof(changes)); Requires.Argument(!snapshotFilters.IsDefault, nameof(snapshotFilters), "Cannot be default."); Requires.NotNull(subTreeProviderByProviderType, nameof(subTreeProviderByProviderType)); bool anyChanges = false; ITargetFramework targetFramework = previousSnapshot.TargetFramework; var worldBuilder = previousSnapshot.DependenciesWorld.ToBuilder(); if (changes.RemovedNodes.Count != 0) { var context = new RemoveDependencyContext(worldBuilder); foreach (IDependencyModel removed in changes.RemovedNodes) { Remove(context, removed); } } if (changes.AddedNodes.Count != 0) { var context = new AddDependencyContext(worldBuilder); foreach (IDependencyModel added in changes.AddedNodes) { Add(context, added); } } // Also factor in any changes to path/framework/catalogs anyChanges = anyChanges || !StringComparers.Paths.Equals(projectPath, previousSnapshot.ProjectPath) || !targetFramework.Equals(previousSnapshot.TargetFramework) || !Equals(catalogs, previousSnapshot.Catalogs); if (anyChanges) { return(new TargetedDependenciesSnapshot( projectPath, targetFramework, catalogs, worldBuilder.ToImmutable())); } return(previousSnapshot); void Remove(RemoveDependencyContext context, IDependencyModel dependencyModel) { string dependencyId = Dependency.GetID( targetFramework, dependencyModel.ProviderType, dependencyModel.Id); if (!context.TryGetDependency(dependencyId, out IDependency dependency)) { return; } context.Reset(); foreach (IDependenciesSnapshotFilter filter in snapshotFilters) { filter.BeforeRemove( targetFramework, dependency, context); anyChanges |= context.Changed; if (!context.GetResult(filter)) { // TODO breaking here denies later filters the opportunity to modify builders return; } } worldBuilder.Remove(dependencyId); anyChanges = true; } void Add(AddDependencyContext context, IDependencyModel dependencyModel) { // Create the unfiltered dependency IDependency?dependency = new Dependency(dependencyModel, targetFramework, projectPath); context.Reset(); foreach (IDependenciesSnapshotFilter filter in snapshotFilters) { filter.BeforeAddOrUpdate( targetFramework, dependency, subTreeProviderByProviderType, projectItemSpecs, context); dependency = context.GetResult(filter); if (dependency == null) { break; } } if (dependency != null) { // A dependency was accepted worldBuilder.Remove(dependency.Id); worldBuilder.Add(dependency.Id, dependency); anyChanges = true; } else { // Even though the dependency was rejected, it's possible that filters made // changes to other dependencies. anyChanges |= context.Changed; } } }
/// <summary> /// Applies changes to <paramref name="previousSnapshot"/> and produces a new snapshot if required. /// If no changes are made, <paramref name="previousSnapshot"/> is returned unmodified. /// </summary> /// <returns>An updated snapshot, or <paramref name="previousSnapshot"/> if no changes occured.</returns> public static TargetedDependenciesSnapshot FromChanges( TargetedDependenciesSnapshot previousSnapshot, IDependenciesChanges?changes, IProjectCatalogSnapshot?catalogs, ImmutableArray <IDependenciesSnapshotFilter> snapshotFilters, IReadOnlyDictionary <string, IProjectDependenciesSubTreeProvider> subTreeProviderByProviderType, IImmutableSet <string>?projectItemSpecs) { Requires.NotNull(previousSnapshot, nameof(previousSnapshot)); Requires.Argument(!snapshotFilters.IsDefault, nameof(snapshotFilters), "Cannot be default."); Requires.NotNull(subTreeProviderByProviderType, nameof(subTreeProviderByProviderType)); bool anyChanges = false; ITargetFramework targetFramework = previousSnapshot.TargetFramework; var dependencyById = previousSnapshot.Dependencies.ToDictionary(d => d.Id, StringComparers.DependencyTreeIds); if (changes != null && changes.RemovedNodes.Count != 0) { var context = new RemoveDependencyContext(dependencyById); foreach (IDependencyModel removed in changes.RemovedNodes) { Remove(context, removed); } } if (changes != null && changes.AddedNodes.Count != 0) { var context = new AddDependencyContext(dependencyById); foreach (IDependencyModel added in changes.AddedNodes) { #pragma warning disable CS0618 // Type or member is obsolete // NOTE we still need to check this in case extensions (eg. WebTools) provide us with top level items that need to be filtered out if (!added.TopLevel) { continue; } #pragma warning restore CS0618 // Type or member is obsolete Add(context, added); } } // Also factor in any changes to path/framework/catalogs anyChanges = anyChanges || !targetFramework.Equals(previousSnapshot.TargetFramework) || !Equals(catalogs, previousSnapshot.Catalogs); if (anyChanges) { return(new TargetedDependenciesSnapshot( targetFramework, catalogs, dependencyById.ToImmutableValueArray())); } return(previousSnapshot); void Remove(RemoveDependencyContext context, IDependencyModel dependencyModel) { string dependencyId = Dependency.GetID( targetFramework, dependencyModel.ProviderType, dependencyModel.Id); if (!context.TryGetDependency(dependencyId, out IDependency dependency)) { return; } context.Reset(); foreach (IDependenciesSnapshotFilter filter in snapshotFilters) { filter.BeforeRemove( targetFramework, dependency, context); anyChanges |= context.Changed; if (!context.GetResult(filter)) { // TODO breaking here denies later filters the opportunity to modify builders return; } } dependencyById.Remove(dependencyId); anyChanges = true; } void Add(AddDependencyContext context, IDependencyModel dependencyModel) { // Create the unfiltered dependency IDependency?dependency = new Dependency(dependencyModel, targetFramework); context.Reset(); foreach (IDependenciesSnapshotFilter filter in snapshotFilters) { filter.BeforeAddOrUpdate( targetFramework, dependency, subTreeProviderByProviderType, projectItemSpecs, context); dependency = context.GetResult(filter); if (dependency == null) { break; } } if (dependency != null) { // A dependency was accepted dependencyById.Remove(dependency.Id); dependencyById.Add(dependency.Id, dependency); anyChanges = true; } else { // Even though the dependency was rejected, it's possible that filters made // changes to other dependencies. anyChanges |= context.Changed; } } }