public void GetSpecDependencies_WithAssetTargetFallback_AndDependencyResolutionVariableSpecified_ReturnsCorrectDependencies(string assetTargetFallbackEnvironmentVariableValue, int dependencyCount)
        {
            // Arrange
            var net60Framework  = FrameworkConstants.CommonFrameworks.Net60;
            var net472Framework = FrameworkConstants.CommonFrameworks.Net472;
            var packageSpec     = ProjectTestHelpers.GetPackageSpec(rootPath: "C:\\", projectName: "A", framework: net472Framework.GetShortFolderName(), dependencyName: "x");

            var envVarWrapper = new TestEnvironmentVariableReader(new Dictionary <string, string> {
                { "NUGET_USE_LEGACY_ASSET_TARGET_FALLBACK_DEPENDENCY_RESOLUTION", assetTargetFallbackEnvironmentVariableValue }
            });
            var dependencyProvider  = new PackageSpecReferenceDependencyProvider(new List <ExternalProjectReference>(), NullLogger.Instance, envVarWrapper);
            var assetTargetFallback = new AssetTargetFallbackFramework(net60Framework, new List <NuGetFramework> {
                net472Framework
            });
            // Act

            var dependencies = dependencyProvider.GetSpecDependencies(packageSpec, assetTargetFallback);

            // Assert
            dependencies.Should().HaveCount(dependencyCount);

            if (dependencyCount > 0)
            {
                dependencies[0].Name.Should().Be("x");
            }
        }
        public async Task RestoreAsync_WithProgressReporter_WhenFilesAreWriten_ProgressIsReported()
        {
            // Arrange
            using var pathContext = new SimpleTestPathContext();
            var settings         = Settings.LoadDefaultSettings(pathContext.SolutionRoot);
            var packageSpec      = ProjectTestHelpers.GetPackageSpec(settings, projectName: "projectName", rootPath: pathContext.SolutionRoot);
            var progressReporter = new Mock <IRestoreProgressReporter>();

            // Act
            IReadOnlyList <RestoreSummary> result = await DependencyGraphRestoreUtility.RestoreAsync(
                ProjectTestHelpers.GetDGSpecFromPackageSpecs(packageSpec),
                new DependencyGraphCacheContext(),
                new RestoreCommandProvidersCache(),
                cacheContextModifier : _ => { },
                sources : new SourceRepository[0],
                parentId : Guid.Empty,
                forceRestore : false,
                isRestoreOriginalAction : true,
                additionalMessages : null,
                progressReporter : progressReporter.Object,
                new TestLogger(),
                CancellationToken.None);

            // Assert
            result.Should().HaveCount(1);
            RestoreSummary restoreSummary = result[0];

            restoreSummary.Success.Should().BeTrue();
            restoreSummary.NoOpRestore.Should().BeFalse();
            var assetsFilePath = Path.Combine(packageSpec.RestoreMetadata.OutputPath, LockFileFormat.AssetsFileName);

            File.Exists(assetsFilePath).Should().BeTrue(because: $"{assetsFilePath}");

            var propsFile   = BuildAssetsUtils.GetMSBuildFilePath(packageSpec, BuildAssetsUtils.PropsExtension);
            var targetsFile = BuildAssetsUtils.GetMSBuildFilePath(packageSpec, BuildAssetsUtils.TargetsExtension);

            IReadOnlyList <string> expectedFileList = new string[] { assetsFilePath, propsFile, targetsFile };
            var pathComparer = PathUtility.GetStringComparerBasedOnOS();

            progressReporter.Verify(r =>
                                    r.StartProjectUpdate(
                                        It.Is <string>(e => e.Equals(packageSpec.FilePath)),
                                        It.Is <IReadOnlyList <string> >(e => e.OrderedEquals(expectedFileList, (f) => f, pathComparer, pathComparer))),
                                    Times.Once);
            progressReporter.Verify(r =>
                                    r.EndProjectUpdate(
                                        It.Is <string>(e => e.Equals(packageSpec.FilePath)),
                                        It.Is <IReadOnlyList <string> >(e => e.OrderedEquals(expectedFileList, (f) => f, pathComparer, pathComparer))),
                                    Times.Once);
        }
        public async Task RestoreAsync_WithProgressReporter_WithMultipleProjects_ProgressIsNotReportedForChangedProjetsOnly()
        {
            // Arrange
            using var pathContext = new SimpleTestPathContext();
            var settings         = Settings.LoadDefaultSettings(pathContext.SolutionRoot);
            var project1         = ProjectTestHelpers.GetPackageSpec(settings, projectName: "project1", rootPath: pathContext.SolutionRoot);
            var project2         = ProjectTestHelpers.GetPackageSpec(settings, projectName: "project2", rootPath: pathContext.SolutionRoot);
            var progressReporter = new Mock <IRestoreProgressReporter>();

            // Pre-Conditions
            IReadOnlyList <RestoreSummary> result = await DependencyGraphRestoreUtility.RestoreAsync(
                ProjectTestHelpers.GetDGSpecFromPackageSpecs(project1, project2),
                new DependencyGraphCacheContext(),
                new RestoreCommandProvidersCache(),
                cacheContextModifier : _ => { },
                sources : new SourceRepository[0],
                parentId : Guid.Empty,
                forceRestore : false,
                isRestoreOriginalAction : true,
                additionalMessages : null,
                progressReporter : progressReporter.Object,
                new TestLogger(),
                CancellationToken.None);

            // Pre-Conditions
            result.Should().HaveCount(2);
            foreach (RestoreSummary restoreSummary in result)
            {
                restoreSummary.Success.Should().BeTrue();
                restoreSummary.NoOpRestore.Should().BeFalse();
            }

            progressReporter.Verify(r =>
                                    r.StartProjectUpdate(
                                        It.Is <string>(e => e.Equals(project1.FilePath)),
                                        It.IsAny <IReadOnlyList <string> >()),
                                    Times.Once);
            progressReporter.Verify(r =>
                                    r.EndProjectUpdate(
                                        It.Is <string>(e => e.Equals(project1.FilePath)),
                                        It.IsAny <IReadOnlyList <string> >()),
                                    Times.Once);

            progressReporter.Verify(r =>
                                    r.StartProjectUpdate(
                                        It.Is <string>(e => e.Equals(project2.FilePath)),
                                        It.IsAny <IReadOnlyList <string> >()),
                                    Times.Once);
            progressReporter.Verify(r =>
                                    r.EndProjectUpdate(
                                        It.Is <string>(e => e.Equals(project2.FilePath)),
                                        It.IsAny <IReadOnlyList <string> >()),
                                    Times.Once);

            progressReporter.Verify(r =>
                                    r.StartProjectUpdate(
                                        It.IsAny <string>(),
                                        It.IsAny <IReadOnlyList <string> >()),
                                    Times.Exactly(2));
            progressReporter.Verify(r =>
                                    r.EndProjectUpdate(
                                        It.IsAny <string>(),
                                        It.IsAny <IReadOnlyList <string> >()),
                                    Times.Exactly(2));

            var secondaryProgressReporter = new Mock <IRestoreProgressReporter>();

            // Act
            result = await DependencyGraphRestoreUtility.RestoreAsync(
                ProjectTestHelpers.GetDGSpecFromPackageSpecs(project1.WithTestProjectReference(project2), project2),
                new DependencyGraphCacheContext(),
                new RestoreCommandProvidersCache(),
                cacheContextModifier : _ => { },
                sources : new SourceRepository[0],
                parentId : Guid.Empty,
                forceRestore : false,
                isRestoreOriginalAction : true,
                additionalMessages : null,
                progressReporter : secondaryProgressReporter.Object,
                new TestLogger(),
                CancellationToken.None);

            // Assert
            result.Should().HaveCount(2);
            var project1Summary = result.Single(e => e.InputPath.Equals(project1.FilePath));
            var project2Summary = result.Single(e => e.InputPath.Equals(project2.FilePath));

            project1Summary.Success.Should().BeTrue();
            project1Summary.NoOpRestore.Should().BeFalse();

            // One no-op
            project2Summary.Success.Should().BeTrue();
            project2Summary.NoOpRestore.Should().BeTrue();

            progressReporter.Verify(r =>
                                    r.StartProjectUpdate(
                                        It.Is <string>(e => e.Equals(project1.FilePath)),
                                        It.IsAny <IReadOnlyList <string> >()),
                                    Times.Once);
            progressReporter.Verify(r =>
                                    r.EndProjectUpdate(
                                        It.Is <string>(e => e.Equals(project1.FilePath)),
                                        It.IsAny <IReadOnlyList <string> >()),
                                    Times.Once);
        }
        public async Task RestoreAsync_WithProgressReporter_WhenProjectNoOps_ProgressIsNotReported()
        {
            // Arrange
            using var pathContext = new SimpleTestPathContext();
            var settings         = Settings.LoadDefaultSettings(pathContext.SolutionRoot);
            var packageSpec      = ProjectTestHelpers.GetPackageSpec(settings, projectName: "projectName", rootPath: pathContext.SolutionRoot);
            var dgSpec           = ProjectTestHelpers.GetDGSpecFromPackageSpecs(packageSpec);
            var progressReporter = new Mock <IRestoreProgressReporter>();

            // Pre-Conditions
            IReadOnlyList <RestoreSummary> result = await DependencyGraphRestoreUtility.RestoreAsync(
                dgSpec,
                new DependencyGraphCacheContext(),
                new RestoreCommandProvidersCache(),
                cacheContextModifier : _ => { },
                sources : new SourceRepository[0],
                parentId : Guid.Empty,
                forceRestore : false,
                isRestoreOriginalAction : true,
                additionalMessages : null,
                progressReporter : progressReporter.Object,
                new TestLogger(),
                CancellationToken.None);

            // Pre-Conditions
            result.Should().HaveCount(1);
            RestoreSummary restoreSummary = result[0];

            restoreSummary.Success.Should().BeTrue();
            restoreSummary.NoOpRestore.Should().BeFalse();

            progressReporter.Verify(r =>
                                    r.StartProjectUpdate(
                                        It.IsAny <string>(),
                                        It.IsAny <IReadOnlyList <string> >()),
                                    Times.Once);
            progressReporter.Verify(r =>
                                    r.EndProjectUpdate(
                                        It.IsAny <string>(),
                                        It.IsAny <IReadOnlyList <string> >()),
                                    Times.Once);

            var noopProgressReporter = new Mock <IRestoreProgressReporter>();

            // Act
            result = await DependencyGraphRestoreUtility.RestoreAsync(
                dgSpec,
                new DependencyGraphCacheContext(),
                new RestoreCommandProvidersCache(),
                cacheContextModifier : _ => { },
                sources : new SourceRepository[0],
                parentId : Guid.Empty,
                forceRestore : false,
                isRestoreOriginalAction : true,
                additionalMessages : null,
                progressReporter : noopProgressReporter.Object,
                new TestLogger(),
                CancellationToken.None);

            // Assert
            result.Should().HaveCount(1);
            restoreSummary = result[0];
            restoreSummary.Success.Should().BeTrue();
            restoreSummary.NoOpRestore.Should().BeTrue();

            noopProgressReporter.Verify(r =>
                                        r.StartProjectUpdate(
                                            It.IsAny <string>(),
                                            It.IsAny <IReadOnlyList <string> >()),
                                        Times.Never);
            noopProgressReporter.Verify(r =>
                                        r.EndProjectUpdate(
                                            It.IsAny <string>(),
                                            It.IsAny <IReadOnlyList <string> >()),
                                        Times.Never);
        }
        public async Task GetUpdateActionsAsync_WithPackageReferenceProject_WhenUpdatingPackage_ReturnsCorrectActions()
        {
            const string projectName        = "a";
            string       projectId          = Guid.NewGuid().ToString();
            var          projectSystemCache = new ProjectSystemCache();

            using (TestDirectory testDirectory = TestDirectory.Create())
            {
                var    packageV1 = new SimpleTestPackageContext(packageId: "b", version: "1.0.0");
                var    packageV2 = new SimpleTestPackageContext(packageV1.Id, version: "2.0.0");
                string packageSourceDirectoryPath = Path.Combine(testDirectory, "packageSource");

                await SimpleTestPackageUtility.CreateFolderFeedV3Async(
                    packageSourceDirectoryPath,
                    PackageSaveMode.Defaultv3,
                    packageV1,
                    packageV2);

                var packageSource  = new PackageSource(packageSourceDirectoryPath);
                var packageSources = new List <PackageSource>()
                {
                    packageSource
                };

                Initialize(packageSources);

                var unconfiguredProject      = new Mock <UnconfiguredProject>();
                var configuredProject        = new Mock <ConfiguredProject>();
                var projectServices          = new Mock <ConfiguredProjectServices>();
                var packageReferencesService = new Mock <IPackageReferencesService>();
                var result = new Mock <IUnresolvedPackageReference>();

                unconfiguredProject.Setup(x => x.GetSuggestedConfiguredProjectAsync())
                .ReturnsAsync(configuredProject.Object);

                configuredProject.SetupGet(x => x.Services)
                .Returns(projectServices.Object);

                projectServices.SetupGet(x => x.PackageReferences)
                .Returns(packageReferencesService.Object);

                packageReferencesService.Setup(x => x.AddAsync(It.IsNotNull <string>(), It.IsNotNull <string>()))
                .ReturnsAsync(new AddReferenceResult <IUnresolvedPackageReference>(result.Object, added: true));

                var nuGetProjectServices = new Mock <INuGetProjectServices>();

                nuGetProjectServices.SetupGet(x => x.ScriptService)
                .Returns(Mock.Of <IProjectScriptHostService>());

                PackageSpec packageSpec     = ProjectTestHelpers.GetPackageSpec(projectName, testDirectory);
                var         projectFullPath = packageSpec.RestoreMetadata.ProjectPath;

                var project = new CpsPackageReferenceProject(
                    projectName: projectName,
                    projectUniqueName: projectFullPath,
                    projectFullPath: projectFullPath,
                    projectSystemCache,
                    unconfiguredProject.Object,
                    nuGetProjectServices.Object,
                    projectId);


                DependencyGraphSpec projectRestoreInfo = ProjectTestHelpers.GetDGSpecFromPackageSpecs(packageSpec);
                projectRestoreInfo.AddProject(packageSpec);
                var projectNames = new ProjectNames(
                    fullName: projectFullPath,
                    uniqueName: projectFullPath,
                    shortName: projectName,
                    customUniqueName: projectName,
                    projectId: projectId);
                projectSystemCache.AddProjectRestoreInfo(projectNames, projectRestoreInfo, Array.Empty <IAssetsLogMessage>());

                _solutionManager.NuGetProjects.Add(project);

                string[] projectIds         = new[] { projectId };
                string[] packageSourceNames = new[] { packageSource.Name };

                await PerformOperationAsync(async (projectManager) =>
                {
                    IReadOnlyList <ProjectAction> actions = await projectManager.GetInstallActionsAsync(
                        projectIds,
                        packageV1.Identity,
                        VersionConstraints.None,
                        includePrelease: true,
                        DependencyBehavior.Lowest,
                        packageSourceNames,
                        CancellationToken.None);

                    Assert.NotEmpty(actions);
                    Assert.Equal(1, actions.Count);

                    ProjectAction action = actions[0];

                    Assert.Equal(packageV1.Identity, action.PackageIdentity);
                    Assert.Equal(NuGetProjectActionType.Install, action.ProjectActionType);
                    Assert.Equal(projectId, action.ProjectId);

                    Assert.Equal(1, action.ImplicitActions.Count);

                    ImplicitProjectAction implicitAction = action.ImplicitActions[0];

                    Assert.Equal(packageV1.Identity, implicitAction.PackageIdentity);
                    Assert.Equal(NuGetProjectActionType.Install, implicitAction.ProjectActionType);

                    await projectManager.ExecuteActionsAsync(actions, CancellationToken.None);

                    AddPackageDependency(projectSystemCache, projectNames, packageSpec, packageV1);
                });

                await PerformOperationAsync(async (projectManager) =>
                {
                    IReadOnlyList <ProjectAction> actions = await projectManager.GetUpdateActionsAsync(
                        projectIds,
                        new[] { packageV2.Identity },
                        VersionConstraints.None,
                        includePrelease: true,
                        DependencyBehavior.Lowest,
                        packageSourceNames,
                        CancellationToken.None);

                    Assert.NotEmpty(actions);
                    Assert.Equal(1, actions.Count);

                    ProjectAction action = actions[0];

                    Assert.Equal(packageV2.Identity, action.PackageIdentity);
                    Assert.Equal(NuGetProjectActionType.Install, action.ProjectActionType);
                    Assert.Equal(projectId, action.ProjectId);

                    Assert.Equal(2, action.ImplicitActions.Count);

                    ImplicitProjectAction implicitAction = action.ImplicitActions[0];

                    Assert.Equal(packageV1.Identity, implicitAction.PackageIdentity);
                    Assert.Equal(NuGetProjectActionType.Uninstall, implicitAction.ProjectActionType);

                    implicitAction = action.ImplicitActions[1];

                    Assert.Equal(packageV2.Identity, implicitAction.PackageIdentity);
                    Assert.Equal(NuGetProjectActionType.Install, implicitAction.ProjectActionType);
                });
            }
        }