2019-07-11 16:35:37 -07:00
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2024-10-17 12:31:15 -07:00
using System ;
2020-04-13 09:31:48 -07:00
using System.Collections.Generic ;
2024-10-17 12:31:15 -07:00
using System.Collections.Immutable ;
2019-07-11 16:35:37 -07:00
using System.Linq ;
2026-01-30 13:46:26 -08:00
using FluentAssertions ;
2020-12-23 14:14:24 -08:00
using NuGet.Commands.Test ;
2020-04-13 09:31:48 -07:00
using NuGet.LibraryModel ;
2020-12-23 14:14:24 -08:00
using NuGet.Packaging.Core ;
2020-04-13 09:31:48 -07:00
using NuGet.Versioning ;
2019-07-11 16:35:37 -07:00
using Xunit ;
using static NuGet . Frameworks . FrameworkConstants ;
using PackagesLockFileBuilder = NuGet . ProjectModel . Test . Builders . PackagesLockFileBuilder ;
namespace NuGet.ProjectModel.Test.ProjectLockFile
{
public class LockFileUtilitiesTests
{
[Fact]
public void IsLockFileStillValid_DifferentVersions_AreNotEqual ()
{
var x = new PackagesLockFileBuilder (). Build ();
var y = new PackagesLockFileBuilder ()
2020-04-13 09:31:48 -07:00
. WithVersion ( PackagesLockFileFormat . Version + 1 )
2019-07-11 16:35:37 -07:00
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileStillValid ( x , y );
Assert . False ( actual . IsValid );
actual = PackagesLockFileUtilities . IsLockFileStillValid ( y , x );
Assert . False ( actual . IsValid );
}
[Fact]
public void IsLockFileStillValid_DifferentTargetCounts_AreNotEqual ()
{
var x = new PackagesLockFileBuilder ()
. WithTarget ( target => target . WithFramework ( CommonFrameworks . NetStandard20 ))
. WithTarget ( target => target . WithFramework ( CommonFrameworks . NetCoreApp22 ))
. Build ();
var y = new PackagesLockFileBuilder ()
. WithTarget ( target => target . WithFramework ( CommonFrameworks . NetStandard20 ))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileStillValid ( x , y );
Assert . False ( actual . IsValid );
actual = PackagesLockFileUtilities . IsLockFileStillValid ( y , x );
Assert . False ( actual . IsValid );
}
[Fact]
public void IsLockFileStillValid_DifferentTargets_AreNotEqual ()
{
var x = new PackagesLockFileBuilder ()
. WithTarget ( target => target . WithFramework ( CommonFrameworks . NetStandard20 ))
. Build ();
var y = new PackagesLockFileBuilder ()
. WithTarget ( target => target . WithFramework ( CommonFrameworks . NetCoreApp22 ))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileStillValid ( x , y );
Assert . False ( actual . IsValid );
actual = PackagesLockFileUtilities . IsLockFileStillValid ( y , x );
Assert . False ( actual . IsValid );
}
[Fact]
public void IsLockFileStillValid_DifferentDependencyCounts_AreNotEqual ()
{
var x = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep . WithId ( "PackageA" )))
. Build ();
var y = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep . WithId ( "PackageA" ))
. WithDependency ( dep => dep . WithId ( "PackageB" )))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileStillValid ( x , y );
Assert . False ( actual . IsValid );
actual = PackagesLockFileUtilities . IsLockFileStillValid ( y , x );
Assert . False ( actual . IsValid );
}
[Fact]
public void IsLockFileStillValid_DifferentDependency_AreNotEqual ()
{
var x = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep . WithId ( "PackageA" )))
. Build ();
var y = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep . WithId ( "PackageB" )))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileStillValid ( x , y );
Assert . False ( actual . IsValid );
actual = PackagesLockFileUtilities . IsLockFileStillValid ( y , x );
Assert . False ( actual . IsValid );
}
[Fact]
public void IsLockFileStillValid_MatchesDependencies_AreEqual ()
{
var x = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "PackageA" )
. WithContentHash ( "ABC" ))
. WithDependency ( dep => dep
. WithId ( "PackageB" )
. WithContentHash ( "123" )))
. Build ();
var y = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "PackageA" )
. WithContentHash ( "XYZ" ))
. WithDependency ( dep => dep
. WithId ( "PackageB" )
. WithContentHash ( "890" )))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileStillValid ( x , y );
Assert . True ( actual . IsValid );
Assert . NotNull ( actual . MatchedDependencies );
Assert . Equal ( 2 , actual . MatchedDependencies . Count );
var depKvp = actual . MatchedDependencies . Single ( d => d . Key . Id == "PackageA" );
Assert . Equal ( "ABC" , depKvp . Key . ContentHash );
Assert . Equal ( "XYZ" , depKvp . Value . ContentHash );
depKvp = actual . MatchedDependencies . Single ( d => d . Key . Id == "PackageB" );
Assert . Equal ( "123" , depKvp . Key . ContentHash );
Assert . Equal ( "890" , depKvp . Value . ContentHash );
actual = PackagesLockFileUtilities . IsLockFileStillValid ( y , x );
Assert . True ( actual . IsValid );
Assert . NotNull ( actual . MatchedDependencies );
Assert . Equal ( 2 , actual . MatchedDependencies . Count );
depKvp = actual . MatchedDependencies . Single ( d => d . Key . Id == "PackageA" );
Assert . Equal ( "ABC" , depKvp . Value . ContentHash );
Assert . Equal ( "XYZ" , depKvp . Key . ContentHash );
depKvp = actual . MatchedDependencies . Single ( d => d . Key . Id == "PackageB" );
Assert . Equal ( "123" , depKvp . Value . ContentHash );
Assert . Equal ( "890" , depKvp . Key . ContentHash );
}
2020-04-13 09:31:48 -07:00
2021-02-22 21:25:19 -08:00
[Fact]
public void IsLockFileStillValid_DifferentTargetFrameworksInDgspec_InvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
var projectName = "project" ;
var dependency1 = new LibraryDependency (
new LibraryRange ( "library1" , versionRange : VersionRange . Parse ( "1.0.0" ), LibraryDependencyTarget . Package ),
LibraryIncludeFlags . All ,
LibraryIncludeFlags . All ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2021-02-22 21:25:19 -08:00
autoReferenced : false ,
generatePathProperty : true ,
versionCentrallyManaged : false ,
LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : "stuff" ,
versionOverride : null );
2021-02-22 21:25:19 -08:00
var tfm1 = new TargetFrameworkInformation
{
2024-10-17 12:31:15 -07:00
Dependencies = [ dependency1 ],
2021-02-22 21:25:19 -08:00
FrameworkName = framework
};
var tfm2 = new TargetFrameworkInformation
{
FrameworkName = CommonFrameworks . NetCoreApp31
};
var project = new PackageSpec ( new List < TargetFrameworkInformation >() { tfm1 , tfm2 })
{
RestoreMetadata = new ProjectRestoreMetadata () { ProjectUniqueName = projectName , CentralPackageVersionsEnabled = false }
};
DependencyGraphSpec dgSpec = new DependencyGraphSpec ();
dgSpec . AddRestore ( projectName );
dgSpec . AddProject ( project );
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "library1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "otherDep" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Transitive )))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( "The project target frameworks are different than the lock file's target frameworks. " +
"Lock file target frameworks: netstandard2.0,netcoreapp3.1. Project target frameworks netstandard2.0." , actual . InvalidReasons );
}
[Fact]
public void IsLockFileStillValid_NewTargetFrameworksInDgspec_InvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
var projectName = "project" ;
var dependency1 = new LibraryDependency (
new LibraryRange ( "library1" , versionRange : VersionRange . Parse ( "1.0.0" ), LibraryDependencyTarget . Package ),
LibraryIncludeFlags . All ,
LibraryIncludeFlags . All ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2021-02-22 21:25:19 -08:00
autoReferenced : false ,
generatePathProperty : true ,
versionCentrallyManaged : false ,
LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : "stuff" ,
versionOverride : null );
2021-02-22 21:25:19 -08:00
var tfm = new TargetFrameworkInformation
{
2024-10-17 12:31:15 -07:00
Dependencies = [ dependency1 ],
2021-02-22 21:25:19 -08:00
FrameworkName = framework
};
var project = new PackageSpec ( new List < TargetFrameworkInformation >() { tfm })
{
RestoreMetadata = new ProjectRestoreMetadata () { ProjectUniqueName = projectName , CentralPackageVersionsEnabled = false }
};
DependencyGraphSpec dgSpec = new DependencyGraphSpec ();
dgSpec . AddRestore ( projectName );
dgSpec . AddProject ( project );
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetCoreApp31 )
. WithDependency ( dep => dep
. WithId ( "library1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "otherDep" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Transitive )))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( "The project target framework netstandard2.0 was not found in the lock file." , actual . InvalidReasons );
}
2020-04-13 09:31:48 -07:00
[Fact]
public void IsLockFileStillValid_RemovedCentralTransitivePackageVersions_InvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
var projectName = "project" ;
var cpvm1 = new CentralPackageVersion ( "cpvm1" , VersionRange . Parse ( "1.0.0" ));
var cpvm2 = new CentralPackageVersion ( "cpvm2" , VersionRange . Parse ( "1.0.0" ));
var dependency1 = new LibraryDependency (
2024-10-17 12:31:15 -07:00
new LibraryRange ( "cpvm1" , versionRange : cpvm1 . VersionRange , LibraryDependencyTarget . Package ),
2020-04-13 09:31:48 -07:00
LibraryIncludeFlags . All ,
LibraryIncludeFlags . All ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2020-04-13 09:31:48 -07:00
autoReferenced : false ,
2020-04-23 12:07:53 -07:00
generatePathProperty : true ,
2024-10-17 12:31:15 -07:00
versionCentrallyManaged : true ,
2020-04-23 12:07:53 -07:00
LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : "stuff" ,
versionOverride : null );
2020-04-13 09:31:48 -07:00
2024-10-17 12:31:15 -07:00
var centralPackageVersions = new Dictionary < string , CentralPackageVersion >( StringComparer . OrdinalIgnoreCase )
{
{ "cpvm1" , cpvm1 },
{ "cpvm2" , cpvm2 },
};
ImmutableArray < LibraryDependency > dependencies = [ dependency1 ];
var tfm = new TargetFrameworkInformation ()
{
CentralPackageVersions = centralPackageVersions ,
Dependencies = dependencies ,
FrameworkName = framework
};
2020-04-13 09:31:48 -07:00
var project = new PackageSpec ( new List < TargetFrameworkInformation >() { tfm });
project . RestoreMetadata = new ProjectRestoreMetadata () { ProjectUniqueName = projectName , CentralPackageVersionsEnabled = true };
DependencyGraphSpec dgSpec = new DependencyGraphSpec ();
dgSpec . AddRestore ( projectName );
dgSpec . AddProject ( project );
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "cpvm1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "cpvm2" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . CentralTransitive ))
. WithDependency ( dep => dep
. WithId ( "cpvm3" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . CentralTransitive )))
. Build ();
// The central package version cpvm3 it was removed
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( "Central package management file(s) doesn't contain version range for cpvm3 package " +
"which is specified as CentralTransitive dependency in the lock file." , actual . InvalidReasons );
2020-04-13 09:31:48 -07:00
}
[Fact]
public void IsLockFileStillValid_DifferentCentralTransitivePackageVersions_InvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
var projectName = "project" ;
var cpvm1 = new CentralPackageVersion ( "cpvm1" , VersionRange . Parse ( "1.0.0" ));
var cpvm2 = new CentralPackageVersion ( "cpvm2" , VersionRange . Parse ( "2.0.0" ));
var dependency1 = new LibraryDependency (
2024-10-17 12:31:15 -07:00
new LibraryRange ( "cpvm1" , versionRange : cpvm1 . VersionRange , LibraryDependencyTarget . Package ),
2020-04-13 09:31:48 -07:00
LibraryIncludeFlags . All ,
LibraryIncludeFlags . All ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2020-04-13 09:31:48 -07:00
autoReferenced : false ,
2020-04-23 12:07:53 -07:00
generatePathProperty : true ,
2024-10-17 12:31:15 -07:00
versionCentrallyManaged : true ,
2020-04-23 12:07:53 -07:00
LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : "stuff" ,
versionOverride : null );
2020-04-13 09:31:48 -07:00
2024-10-17 12:31:15 -07:00
var centralPackageVersions = new Dictionary < string , CentralPackageVersion >( StringComparer . OrdinalIgnoreCase )
{
{ "cpvm1" , cpvm1 },
{ "cpvm2" , cpvm2 },
};
ImmutableArray < LibraryDependency > dependencies = [ dependency1 ];
var tfm = new TargetFrameworkInformation ()
{
CentralPackageVersions = centralPackageVersions ,
Dependencies = dependencies ,
FrameworkName = framework ,
};
2020-04-13 09:31:48 -07:00
var project = new PackageSpec ( new List < TargetFrameworkInformation >() { tfm });
project . RestoreMetadata = new ProjectRestoreMetadata () { ProjectUniqueName = projectName , CentralPackageVersionsEnabled = true };
DependencyGraphSpec dgSpec = new DependencyGraphSpec ();
dgSpec . AddRestore ( projectName );
dgSpec . AddProject ( project );
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "cpvm1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "cpvm2" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . CentralTransitive )))
. Build ();
// The central package version cpvm2 has version changed
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( "Mistmatch between the requestedVersion of a lock file dependency marked as CentralTransitive and the the version specified in the central package management file. " +
"Lock file version [1.0.0, ), central package management version [2.0.0, )." , actual . InvalidReasons );
2020-04-13 09:31:48 -07:00
}
[Fact]
public void IsLockFileStillValid_DifferentDirectPackageVersions_InvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
var projectName = "project" ;
var cpvm1 = new CentralPackageVersion ( "cpvm1" , VersionRange . Parse ( "2.0.0" ));
var cpvm2 = new CentralPackageVersion ( "cpvm2" , VersionRange . Parse ( "1.0.0" ));
var dependency1 = new LibraryDependency (
2024-10-17 12:31:15 -07:00
new LibraryRange ( "cpvm1" , versionRange : cpvm1 . VersionRange , LibraryDependencyTarget . Package ),
2020-04-13 09:31:48 -07:00
LibraryIncludeFlags . All ,
LibraryIncludeFlags . All ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2020-04-13 09:31:48 -07:00
autoReferenced : false ,
2020-04-23 12:07:53 -07:00
generatePathProperty : true ,
2024-10-17 12:31:15 -07:00
versionCentrallyManaged : true ,
2020-04-23 12:07:53 -07:00
LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : "stuff" ,
versionOverride : null );
2020-04-13 09:31:48 -07:00
2024-10-17 12:31:15 -07:00
var centralPackageVersions = new Dictionary < string , CentralPackageVersion >( StringComparer . OrdinalIgnoreCase )
{
{ "cpvm1" , cpvm1 },
{ "cpvm2" , cpvm2 },
};
ImmutableArray < LibraryDependency > dependencies = [ dependency1 ];
var tfm = new TargetFrameworkInformation ()
{
CentralPackageVersions = centralPackageVersions ,
Dependencies = dependencies ,
FrameworkName = framework
};
2020-04-13 09:31:48 -07:00
var project = new PackageSpec ( new List < TargetFrameworkInformation >() { tfm });
project . RestoreMetadata = new ProjectRestoreMetadata () { ProjectUniqueName = projectName , CentralPackageVersionsEnabled = true };
DependencyGraphSpec dgSpec = new DependencyGraphSpec ();
dgSpec . AddRestore ( projectName );
dgSpec . AddProject ( project );
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "cpvm1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "cpvm2" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . CentralTransitive )))
. Build ();
// The central package version cpvm2 has version changed
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( "The package reference cpvm1 version has changed from [1.0.0, ) to [2.0.0, )." , actual . InvalidReasons );
2020-04-13 09:31:48 -07:00
}
[Fact]
public void IsLockFileStillValid_TransitiveVersionsMovedToCentralFile_InvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
var projectName = "project" ;
var cpvm1 = new CentralPackageVersion ( "cpvm1" , VersionRange . Parse ( "1.0.0" ));
var cpvm2 = new CentralPackageVersion ( "cpvm2" , VersionRange . Parse ( "1.0.0" ));
var dependency1 = new LibraryDependency (
2024-10-17 12:31:15 -07:00
new LibraryRange ( "cpvm1" , versionRange : cpvm1 . VersionRange , LibraryDependencyTarget . Package ),
2020-04-13 09:31:48 -07:00
LibraryIncludeFlags . All ,
LibraryIncludeFlags . All ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2020-04-13 09:31:48 -07:00
autoReferenced : false ,
2020-04-23 12:07:53 -07:00
generatePathProperty : true ,
2024-10-17 12:31:15 -07:00
versionCentrallyManaged : true ,
2020-04-23 12:07:53 -07:00
LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : "stuff" ,
versionOverride : null );
2020-04-13 09:31:48 -07:00
2024-10-17 12:31:15 -07:00
var centralPackageVersions = new Dictionary < string , CentralPackageVersion >( StringComparer . OrdinalIgnoreCase )
{
{ "cpvm1" , cpvm1 },
{ "cpvm2" , cpvm2 },
};
ImmutableArray < LibraryDependency > dependencies = [ dependency1 ];
var tfm = new TargetFrameworkInformation ()
{
CentralPackageVersions = centralPackageVersions ,
Dependencies = dependencies ,
FrameworkName = framework ,
};
2020-04-13 09:31:48 -07:00
var project = new PackageSpec ( new List < TargetFrameworkInformation >() { tfm });
project . RestoreMetadata = new ProjectRestoreMetadata () { ProjectUniqueName = projectName , CentralPackageVersionsEnabled = true };
DependencyGraphSpec dgSpec = new DependencyGraphSpec ();
dgSpec . AddRestore ( projectName );
dgSpec . AddProject ( project );
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "cpvm1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "cpvm2" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Transitive )))
. Build ();
// The central package version cpvm2 has was changed from transitive to central
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( "Transitive dependency cpvm2 moved to be centraly managed invalidated the lock file." , actual . InvalidReasons );
2020-04-13 09:31:48 -07:00
}
[Fact]
public void IsLockFileStillValid_NoChangeInCentralTransitivePackageVersions_DoesNotInvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
var projectName = "project" ;
var cpvm1 = new CentralPackageVersion ( "cpvm1" , VersionRange . Parse ( "1.0.0" ));
var cpvm2 = new CentralPackageVersion ( "cpvm2" , VersionRange . Parse ( "1.0.0" ));
var dependency1 = new LibraryDependency (
2024-10-17 12:31:15 -07:00
new LibraryRange ( "cpvm1" , versionRange : cpvm1 . VersionRange , LibraryDependencyTarget . Package ),
2020-04-13 09:31:48 -07:00
LibraryIncludeFlags . All ,
LibraryIncludeFlags . All ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2020-04-13 09:31:48 -07:00
autoReferenced : false ,
2020-04-23 12:07:53 -07:00
generatePathProperty : true ,
2024-10-17 12:31:15 -07:00
versionCentrallyManaged : true ,
2020-04-23 12:07:53 -07:00
LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : "stuff" ,
versionOverride : null );
2020-04-13 09:31:48 -07:00
2024-10-17 12:31:15 -07:00
var centralPackageVersions = new Dictionary < string , CentralPackageVersion >( StringComparer . OrdinalIgnoreCase )
{
{ "cpvm1" , cpvm1 },
{ "cpvm2" , cpvm2 },
};
ImmutableArray < LibraryDependency > dependencies = [ dependency1 ];
var tfm = new TargetFrameworkInformation ()
{
CentralPackageVersions = centralPackageVersions ,
Dependencies = dependencies ,
FrameworkName = framework
};
2020-04-13 09:31:48 -07:00
var project = new PackageSpec ( new List < TargetFrameworkInformation >() { tfm });
project . RestoreMetadata = new ProjectRestoreMetadata () { ProjectUniqueName = projectName , CentralPackageVersionsEnabled = true };
DependencyGraphSpec dgSpec = new DependencyGraphSpec ();
dgSpec . AddRestore ( projectName );
dgSpec . AddProject ( project );
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "cpvm1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "cpvm2" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . CentralTransitive ))
. WithDependency ( dep => dep
. WithId ( "otherDep" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Transitive )))
. Build ();
// Nothing changed in central package versions
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . True ( actual . IsValid );
Assert . Empty ( actual . InvalidReasons );
2020-04-13 09:31:48 -07:00
}
[Fact]
public void IsLockFileStillValid_TransitiveDependencyNotCentrallyManaged_DoesNotInvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
var projectName = "project" ;
var cpvm1 = new CentralPackageVersion ( "cpvm1" , VersionRange . Parse ( "1.0.0" ));
var cpvm2 = new CentralPackageVersion ( "cpvm2" , VersionRange . Parse ( "1.0.0" ));
var dependency1 = new LibraryDependency (
2024-10-17 12:31:15 -07:00
new LibraryRange ( "cpvm1" , versionRange : cpvm1 . VersionRange , LibraryDependencyTarget . Package ),
2020-04-13 09:31:48 -07:00
LibraryIncludeFlags . All ,
LibraryIncludeFlags . All ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2020-04-13 09:31:48 -07:00
autoReferenced : false ,
2020-04-23 12:07:53 -07:00
generatePathProperty : true ,
2024-10-17 12:31:15 -07:00
versionCentrallyManaged : true ,
2020-04-23 12:07:53 -07:00
LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : "stuff" ,
versionOverride : null );
2020-04-13 09:31:48 -07:00
2024-10-17 12:31:15 -07:00
var centralPackageVersions = new Dictionary < string , CentralPackageVersion >( StringComparer . OrdinalIgnoreCase )
{
{ "cpvm1" , cpvm1 },
{ "cpvm2" , cpvm2 },
};
ImmutableArray < LibraryDependency > dependencies = [ dependency1 ];
var tfm = new TargetFrameworkInformation ()
{
CentralPackageVersions = centralPackageVersions ,
Dependencies = dependencies ,
FrameworkName = framework
};
2020-04-13 09:31:48 -07:00
var project = new PackageSpec ( new List < TargetFrameworkInformation >() { tfm });
project . RestoreMetadata = new ProjectRestoreMetadata () { ProjectUniqueName = projectName , CentralPackageVersionsEnabled = true };
DependencyGraphSpec dgSpec = new DependencyGraphSpec ();
dgSpec . AddRestore ( projectName );
dgSpec . AddProject ( project );
var lockFile1 = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "cpvm1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "otherDep" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Transitive )))
. Build ();
var lockFile2 = new PackagesLockFileBuilder ()
2026-02-24 16:36:11 -08:00
. WithVersion ( 2 )
2020-04-13 09:31:48 -07:00
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "cpvm1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "otherDep" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Transitive )))
. Build ();
// Nothing changed
2021-02-22 21:25:19 -08:00
// different versions of lock file versions are handled
var actual1 = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile1 );
var actual2 = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile2 );
Assert . True ( actual1 . IsValid );
Assert . Empty ( actual1 . InvalidReasons );
Assert . True ( actual2 . IsValid );
Assert . Empty ( actual2 . InvalidReasons );
2020-04-13 09:31:48 -07:00
}
[Fact]
public void IsLockFileStillValid_NoCentralPackageVersions_DoesNotInvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
var projectName = "project" ;
var dependency1 = new LibraryDependency (
new LibraryRange ( "cpvm1" , versionRange : VersionRange . Parse ( "1.0.0" ), LibraryDependencyTarget . Package ),
LibraryIncludeFlags . All ,
LibraryIncludeFlags . All ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2020-04-13 09:31:48 -07:00
autoReferenced : false ,
2020-04-23 12:07:53 -07:00
generatePathProperty : true ,
versionCentrallyManaged : false ,
LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : "stuff" ,
versionOverride : null );
2020-04-13 09:31:48 -07:00
2024-10-17 12:31:15 -07:00
var tfm = new TargetFrameworkInformation ()
{
Dependencies = [ dependency1 ],
FrameworkName = framework
};
2020-04-13 09:31:48 -07:00
var project = new PackageSpec ( new List < TargetFrameworkInformation >() { tfm });
project . RestoreMetadata = new ProjectRestoreMetadata () { ProjectUniqueName = projectName , CentralPackageVersionsEnabled = false };
DependencyGraphSpec dgSpec = new DependencyGraphSpec ();
dgSpec . AddRestore ( projectName );
dgSpec . AddProject ( project );
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "cpvm1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "otherDep" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Transitive )))
. Build ();
// Nothing changed in central package versions
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . True ( actual . IsValid );
Assert . Empty ( actual . InvalidReasons );
2020-04-13 09:31:48 -07:00
}
[Fact]
public void IsLockFileStillValid_VersionValidationCheck ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
var projectName = "project" ;
var dependency1 = new LibraryDependency (
new LibraryRange ( "cpvm1" , versionRange : VersionRange . Parse ( "1.0.0" ), LibraryDependencyTarget . Package ),
LibraryIncludeFlags . All ,
LibraryIncludeFlags . All ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2020-04-13 09:31:48 -07:00
autoReferenced : false ,
2020-04-23 12:07:53 -07:00
generatePathProperty : true ,
versionCentrallyManaged : false ,
LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : "stuff" ,
versionOverride : null );
2020-04-13 09:31:48 -07:00
2024-10-17 12:31:15 -07:00
var tfm = new TargetFrameworkInformation ()
{
Dependencies = [ dependency1 ],
FrameworkName = framework
};
2020-04-13 09:31:48 -07:00
var project = new PackageSpec ( new List < TargetFrameworkInformation >() { tfm });
project . RestoreMetadata = new ProjectRestoreMetadata () { ProjectUniqueName = projectName , CentralPackageVersionsEnabled = false };
DependencyGraphSpec dgSpec = new DependencyGraphSpec ();
dgSpec . AddRestore ( projectName );
dgSpec . AddProject ( project );
var lockFile = new PackagesLockFileBuilder ()
. WithVersion ( PackagesLockFileFormat . PackagesLockFileVersion + 1 )
. WithTarget ( target => target
. WithFramework ( CommonFrameworks . NetStandard20 )
. WithDependency ( dep => dep
. WithId ( "cpvm1" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Direct ))
. WithDependency ( dep => dep
. WithId ( "otherDep" )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithType ( PackageDependencyType . Transitive )))
. Build ();
// Due to the increased version in the lock file the lock should be invalid
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( "Version specified in the packages.lock.json file is incompatible. Current tooling supports version " +
$"{PackagesLockFileFormat.PackagesLockFileVersion} and previous formats." , actual . InvalidReasons );
}
[Fact]
public void IsLockFileStillValid_WithNewProjectDependency_InvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . Net50 ;
var frameworkShortName = framework . GetShortFolderName ();
2023-09-07 17:18:59 -07:00
var projectA = ProjectTestHelpers . GetPackageSpec ( "A" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectB = ProjectTestHelpers . GetPackageSpec ( "B" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectC = ProjectTestHelpers . GetPackageSpec ( "C" , framework : frameworkShortName ). WithTestRestoreMetadata ();
2021-02-22 21:25:19 -08:00
// A -> B
projectA = projectA . WithTestProjectReference ( projectB );
// A -> C
projectA = projectA . WithTestProjectReference ( projectC );
2023-09-07 17:18:59 -07:00
var dgSpec = ProjectTestHelpers . GetDGSpecForFirstProject ( projectA , projectB , projectC );
2021-02-22 21:25:19 -08:00
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( framework )
. WithDependency ( dep => dep
. WithId ( "B" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( "A new project reference to C was found for net5.0 target framework." , actual . InvalidReasons );
}
[Fact]
public void IsLockFileStillValid_WithNewP2PDependency_InvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . Net50 ;
var frameworkShortName = framework . GetShortFolderName ();
2023-09-07 17:18:59 -07:00
var projectA = ProjectTestHelpers . GetPackageSpec ( "A" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectB = ProjectTestHelpers . GetPackageSpec ( "B" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectC = ProjectTestHelpers . GetPackageSpec ( "C" , framework : frameworkShortName ). WithTestRestoreMetadata ();
2021-02-22 21:25:19 -08:00
// B -> C
projectB = projectB . WithTestProjectReference ( projectC );
// A -> B
projectA = projectA . WithTestProjectReference ( projectB );
2023-09-07 17:18:59 -07:00
var dgSpec = ProjectTestHelpers . GetDGSpecForFirstProject ( projectA , projectB , projectC );
2021-02-22 21:25:19 -08:00
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( framework )
. WithDependency ( dep => dep
. WithId ( "B" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( string . Format ( "The project reference B has changed. Current dependencies: {0} lock file's dependencies: None." , projectC . FilePath ), actual . InvalidReasons );
}
[Fact]
public void IsLockFileStillValid_WithChangeInP2PDependency_InvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . Net50 ;
var frameworkShortName = framework . GetShortFolderName ();
2023-09-07 17:18:59 -07:00
var projectA = ProjectTestHelpers . GetPackageSpec ( "A" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectB = ProjectTestHelpers . GetPackageSpec ( "B" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectD = ProjectTestHelpers . GetPackageSpec ( "D" , framework : frameworkShortName ). WithTestRestoreMetadata ();
2021-02-22 21:25:19 -08:00
// B -> D
projectB = projectB . WithTestProjectReference ( projectD );
// A -> B
projectA = projectA . WithTestProjectReference ( projectB );
2023-09-07 17:18:59 -07:00
var dgSpec = ProjectTestHelpers . GetDGSpecForFirstProject ( projectA , projectB , projectD );
2021-02-22 21:25:19 -08:00
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( framework )
. WithDependency ( dep => dep
. WithId ( "B" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithDependency ( new PackageDependency ( "C" , VersionRange . Parse ( "1.0.0" ))))
. WithDependency ( dep => dep
. WithId ( "C" )
. WithType ( PackageDependencyType . Project )))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( "The project references B whose dependencies has changed." , actual . InvalidReasons );
}
[Fact]
public void IsLockFileStillValid_WithChangeInP2PPackageDependency_InvalidateLockFile ()
{
// Arrange
var framework = CommonFrameworks . Net50 ;
var frameworkShortName = framework . GetShortFolderName ();
2023-09-07 17:18:59 -07:00
var projectA = ProjectTestHelpers . GetPackageSpec ( "A" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectB = ProjectTestHelpers . GetPackageSpec ( "B" , framework : frameworkShortName ). WithTestRestoreMetadata ();
2021-02-22 21:25:19 -08:00
// A -> B
projectA = projectA . WithTestProjectReference ( projectB );
var packageC = new LibraryDependency (
new LibraryRange ( "packageC" , versionRange : VersionRange . Parse ( "1.0.0" ), LibraryDependencyTarget . Package ),
includeType : LibraryIncludeFlags . All ,
suppressParent : LibraryIncludeFlagUtils . DefaultSuppressParent ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2021-02-22 21:25:19 -08:00
autoReferenced : false ,
generatePathProperty : true ,
versionCentrallyManaged : false ,
libraryDependencyReferenceType : LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : null ,
versionOverride : null );
2021-02-22 21:25:19 -08:00
2024-10-17 12:31:15 -07:00
var projectBFirstTargetFramework = projectB . TargetFrameworks . First ();
var projectBFirstTargetFrameworkDependencies = projectBFirstTargetFramework . Dependencies . Add ( packageC );
projectBFirstTargetFramework = new TargetFrameworkInformation ( projectBFirstTargetFramework ) { Dependencies = projectBFirstTargetFrameworkDependencies };
projectB . TargetFrameworks [ 0 ] = projectBFirstTargetFramework ;
2021-02-22 21:25:19 -08:00
2023-09-07 17:18:59 -07:00
var dgSpec = ProjectTestHelpers . GetDGSpecForFirstProject ( projectA , projectB );
2021-02-22 21:25:19 -08:00
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( framework )
. WithDependency ( dep => dep
. WithId ( "B" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithDependency ( new PackageDependency ( "packageB" , VersionRange . Parse ( "1.0.0" ))))
. WithDependency ( dep => dep
. WithId ( "packageB" )
. WithType ( PackageDependencyType . Transitive )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . Contains ( "The project references B whose dependencies has changed." , actual . InvalidReasons );
2020-04-13 09:31:48 -07:00
}
2020-12-23 14:14:24 -08:00
/// <summary>
/// A -> B (PrivateAssets)-> C
/// A has packages lock file enabled. Locked should succeed and ignore `C`.
/// </summary>
[Fact]
public void IsLockFileStillValid_WithProjectToProjectWithPrivateAssets_IgnoresSuppressedDependencies ()
{
// Arrange
var framework = CommonFrameworks . Net50 ;
var frameworkShortName = framework . GetShortFolderName ();
2023-09-07 17:18:59 -07:00
var projectA = ProjectTestHelpers . GetPackageSpec ( "A" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectB = ProjectTestHelpers . GetPackageSpec ( "B" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectC = ProjectTestHelpers . GetPackageSpec ( "C" , framework : frameworkShortName ). WithTestRestoreMetadata ();
2020-12-23 14:14:24 -08:00
// B (PrivateAssets.All) -> C
projectB = projectB . WithTestProjectReference ( projectC , privateAssets : LibraryIncludeFlags . All );
// A -> B
projectA = projectA . WithTestProjectReference ( projectB );
2023-09-07 17:18:59 -07:00
var dgSpec = ProjectTestHelpers . GetDGSpecForFirstProject ( projectA , projectB , projectC );
2020-12-23 14:14:24 -08:00
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( framework )
. WithDependency ( dep => dep
. WithId ( "B" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))))
. Build ();
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
2026-01-30 13:46:26 -08:00
actual . IsValid . Should (). BeTrue ( because : string . Join ( Environment . NewLine , actual . InvalidReasons ));
2021-02-22 21:25:19 -08:00
Assert . Empty ( actual . InvalidReasons );
2020-12-23 14:14:24 -08:00
}
/// <summary>
/// A -> B (PrivateAssets)-> C -> PackageC
/// A -> D -> C -> PackageC
/// </summary>
[Fact]
public void IsLockFileStillValid_WithProjectToProject_MultipleEdgesWithDifferentPrivateAssets_IncludesAllDependencies ()
{
// Arrange
var framework = CommonFrameworks . Net50 ;
var frameworkShortName = framework . GetShortFolderName ();
2023-09-07 17:18:59 -07:00
var projectA = ProjectTestHelpers . GetPackageSpec ( "A" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectB = ProjectTestHelpers . GetPackageSpec ( "B" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectC = ProjectTestHelpers . GetPackageSpec ( "C" , framework : frameworkShortName ). WithTestRestoreMetadata ();
var projectD = ProjectTestHelpers . GetPackageSpec ( "D" , framework : frameworkShortName ). WithTestRestoreMetadata ();
2020-12-23 14:14:24 -08:00
var packageC = new LibraryDependency (
new LibraryRange ( "packageC" , versionRange : VersionRange . Parse ( "2.0.0" ), LibraryDependencyTarget . Package ),
includeType : LibraryIncludeFlags . All ,
suppressParent : LibraryIncludeFlagUtils . DefaultSuppressParent ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2020-12-23 14:14:24 -08:00
autoReferenced : false ,
generatePathProperty : true ,
versionCentrallyManaged : false ,
libraryDependencyReferenceType : LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : null ,
versionOverride : null );
2020-12-23 14:14:24 -08:00
// B (PrivateAssets.All) -> C
projectB = projectB . WithTestProjectReference ( projectC , privateAssets : LibraryIncludeFlags . All );
// A -> B
projectA = projectA . WithTestProjectReference ( projectB );
// A -> D
projectA = projectA . WithTestProjectReference ( projectD );
// D -> C
projectD = projectD . WithTestProjectReference ( projectC );
// C -> PackageC
2024-10-17 12:31:15 -07:00
var projectCTargetFrameworkDependencies = projectC . TargetFrameworks . First (). Dependencies . Add ( packageC );
projectC . TargetFrameworks [ 0 ] = new TargetFrameworkInformation ( projectC . TargetFrameworks [ 0 ]) { Dependencies = projectCTargetFrameworkDependencies };
2020-12-23 14:14:24 -08:00
2023-09-07 17:18:59 -07:00
var dgSpec = ProjectTestHelpers . GetDGSpecForFirstProject ( projectA , projectB , projectC , projectD );
2020-12-23 14:14:24 -08:00
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( framework )
. WithDependency ( dep => dep
. WithId ( "B" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" )))
. WithDependency ( dep => dep
. WithId ( "C" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithDependency ( new PackageDependency ( "packageC" , VersionRange . Parse ( "2.0.0" ))))
. WithDependency ( dep => dep
. WithId ( "D" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithDependency ( new PackageDependency ( "C" , VersionRange . Parse ( "1.0.0" ))))
. WithDependency ( dep => dep
. WithId ( "packageC" )
. WithType ( PackageDependencyType . Transitive )
. WithRequestedVersion ( VersionRange . Parse ( "2.0.0" ))
. WithResolvedVersion ( NuGetVersion . Parse ( "2.0.0" ))
))
. Build ();
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . True ( actual . IsValid );
Assert . Empty ( actual . InvalidReasons );
2020-12-23 14:14:24 -08:00
}
2021-01-05 11:24:27 -08:00
// <summary>
/// A(PR) -> B (PC) -> C(PR) -> PackageC
/// </summary>
[Fact]
public void IsLockFileStillValid_WithProjectToProjectPackagesConfig_IncludesAllDependencies ()
{
// Arrange
var framework = CommonFrameworks . Net50 ;
var frameworkShortName = framework . GetShortFolderName ();
2023-09-07 17:18:59 -07:00
var projectA = ProjectTestHelpers . GetPackageSpec ( "A" , framework : frameworkShortName ). WithTestRestoreMetadata ();
2021-02-22 21:25:19 -08:00
var projectB = ProjectTestHelpers . GetPackagesConfigPackageSpec ( "B" );
2023-09-07 17:18:59 -07:00
var projectC = ProjectTestHelpers . GetPackageSpec ( "C" , framework : frameworkShortName ). WithTestRestoreMetadata ();
2021-01-05 11:24:27 -08:00
var packageC = new LibraryDependency (
new LibraryRange ( "packageC" , versionRange : VersionRange . Parse ( "2.0.0" ), LibraryDependencyTarget . Package ),
includeType : LibraryIncludeFlags . All ,
suppressParent : LibraryIncludeFlagUtils . DefaultSuppressParent ,
2024-10-17 12:31:15 -07:00
noWarn : [],
2021-01-05 11:24:27 -08:00
autoReferenced : false ,
generatePathProperty : true ,
versionCentrallyManaged : false ,
libraryDependencyReferenceType : LibraryDependencyReferenceType . Direct ,
2022-02-28 15:02:11 -08:00
aliases : null ,
versionOverride : null );
2021-01-05 11:24:27 -08:00
// B -> C
projectB = projectB . WithTestProjectReference ( projectC );
// A -> B
projectA = projectA . WithTestProjectReference ( projectB );
// C -> PackageC
2024-10-17 12:31:15 -07:00
var projectCTargetFrameworkDependencies = projectC . TargetFrameworks . First (). Dependencies . Add ( packageC );
projectC . TargetFrameworks [ 0 ] = new TargetFrameworkInformation ( projectC . TargetFrameworks [ 0 ]) { Dependencies = projectCTargetFrameworkDependencies };
2021-01-05 11:24:27 -08:00
2023-09-07 17:18:59 -07:00
var dgSpec = ProjectTestHelpers . GetDGSpecForFirstProject ( projectA , projectB , projectC );
2021-01-05 11:24:27 -08:00
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( framework )
. WithDependency ( dep => dep
. WithId ( "B" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithDependency ( new PackageDependency ( "C" , VersionRange . Parse ( "1.0.0" ))))
. WithDependency ( dep => dep
. WithId ( "C" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
. WithDependency ( new PackageDependency ( "packageC" , VersionRange . Parse ( "2.0.0" ))))
. WithDependency ( dep => dep
. WithId ( "packageC" )
. WithType ( PackageDependencyType . Transitive )
. WithRequestedVersion ( VersionRange . Parse ( "2.0.0" ))
. WithResolvedVersion ( NuGetVersion . Parse ( "2.0.0" ))
))
. Build ();
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . True ( actual . IsValid );
Assert . Empty ( actual . InvalidReasons );
2021-01-05 11:24:27 -08:00
}
// <summary>
/// A(PR) -> B (PC), where A and B have incompatible frameworks
/// </summary>
[Fact]
public void IsLockFileStillValid_WithProjectToProjectPackagesConfig_WithIncompatibleFrameworks_IgnoresCompatiblityChecksAndSucceeds ()
{
// Arrange
var framework = CommonFrameworks . NetStandard ;
var frameworkShortName = framework . GetShortFolderName ();
var incompatibleFramework = CommonFrameworks . Net46 ;
2023-09-07 17:18:59 -07:00
var projectA = ProjectTestHelpers . GetPackageSpec ( "A" , framework : frameworkShortName ). WithTestRestoreMetadata ();
2021-02-22 21:25:19 -08:00
var projectB = ProjectTestHelpers . GetPackagesConfigPackageSpec ( "B" , framework : incompatibleFramework . GetShortFolderName ());
2021-01-05 11:24:27 -08:00
// A -> B
projectA = projectA . WithTestProjectReference ( projectB );
2023-09-07 17:18:59 -07:00
var dgSpec = ProjectTestHelpers . GetDGSpecForFirstProject ( projectA , projectB );
2021-01-05 11:24:27 -08:00
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( framework )
. WithDependency ( dep => dep
. WithId ( "B" )
. WithType ( PackageDependencyType . Project )
. WithRequestedVersion ( VersionRange . Parse ( "1.0.0" ))
))
. Build ();
2021-02-22 21:25:19 -08:00
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . True ( actual . IsValid );
Assert . Empty ( actual . InvalidReasons );
2021-01-05 11:24:27 -08:00
}
2025-05-06 09:18:13 -07:00
[Fact]
public void IsLockFileValid_WithNullVersionRange_DoesNotThrow ()
{
// Arrange
var framework = CommonFrameworks . NetStandard20 ;
PackageSpec projectA = ProjectTestHelpers . GetPackageSpec (
projectName : "A" ,
rootPath : @"C:\" ,
framework : framework . GetShortFolderName (),
dependencyName : "PackageA" ,
dependencyVersion : "1.0.0" )
. WithTestRestoreMetadata ()
. WithDependency ( new LibraryDependency ( new LibraryRange ( "PackageA" , LibraryDependencyTarget . Package ))
{
ReferenceType = LibraryDependencyReferenceType . Direct ,
});
// A -> B
var dgSpec = ProjectTestHelpers . GetDGSpecForFirstProject ( projectA );
var lockFile = new PackagesLockFileBuilder ()
. WithTarget ( target => target
. WithFramework ( framework ))
. Build ();
var actual = PackagesLockFileUtilities . IsLockFileValid ( dgSpec , lockFile );
Assert . False ( actual . IsValid );
Assert . NotNull ( actual . InvalidReasons );
Assert . Equal ( 1 , actual . InvalidReasons . Count );
var invalidReason = actual . InvalidReasons . Single ();
Assert . Contains ( "PackageA" , invalidReason );
}
2019-07-11 16:35:37 -07:00
}
}