public void AddProject_RemoveProject_Clear_TriggerNoEvent_WithEventHandler() { // Arrange var target = new ProjectSystemCache(); var projectNames = new ProjectNames( fullName: @"C:\src\project\project.csproj", uniqueName: @"folder\project", shortName: "project", customUniqueName: @"folder\project"); var projectNamesFromFullPath = ProjectNames.FromFullProjectPath(@"C:\src\project\project.csproj"); var projectRestoreInfo = new DependencyGraphSpec(); var eventCount = 0; target.CacheUpdated += delegate(object sender, NuGetEventArgs <string> e) { if (target.TestResetDirtyFlag()) { eventCount++; } }; // Act target.AddProject(projectNames, vsProjectAdapter: null, nuGetProject: null); target.RemoveProject(projectNames.FullName); target.Clear(); // Assert Assert.Equal(target.IsCacheDirty, 0); Assert.Equal(eventCount, 0); }
public void AddProjectRestoreInfo_TriggersNoEvent_NoEventHandler() { // Arrange var target = new ProjectSystemCache(); var projectNames = new ProjectNames( fullName: @"C:\src\project\project.csproj", uniqueName: @"folder\project", shortName: "project", customUniqueName: @"folder\project"); var projectNamesFromFullPath = ProjectNames.FromFullProjectPath(@"C:\src\project\project.csproj"); var projectRestoreInfo = new DependencyGraphSpec(); // Act target.AddProjectRestoreInfo(projectNamesFromFullPath, projectRestoreInfo); target.AddProject(projectNames, vsProjectAdapter: null, nuGetProject: null); // Assert DependencyGraphSpec actual; ProjectNames names; var getPackageSpecSuccess = target.TryGetProjectRestoreInfo(projectNames.FullName, out actual); var getProjectNameSuccess = target.TryGetProjectNames(projectNames.UniqueName, out names); Assert.True(getPackageSpecSuccess); Assert.True(getProjectNameSuccess); Assert.Same(projectRestoreInfo, actual); Assert.Equal(@"folder\project", names.CustomUniqueName); // Cache remains clean since no one is listening to the cache events Assert.Equal(target.IsCacheDirty, 0); }
/// <summary> /// This is where the nominate calls for the IVs1 and IVS3 APIs combine. The reason for this method is to avoid duplication and potential issues /// The issue with this method is that it has some weird custom logging to ensure backward compatibility. It's on the implementer to ensure these calls are correct. /// <param name="projectUniqueName">projectUniqueName</param> /// <param name="projectRestoreInfo">projectRestoreInfo. Can be null</param> /// <param name="projectRestoreInfo2">proectRestoreInfo2. Can be null</param> /// <param name="token"></param> /// <remarks>Exactly one of projectRestoreInfos has to null.</remarks> /// <returns>The task that scheduled restore</returns> private Task <bool> NominateProjectAsync(string projectUniqueName, IVsProjectRestoreInfo projectRestoreInfo, IVsProjectRestoreInfo2 projectRestoreInfo2, CancellationToken token) { if (string.IsNullOrEmpty(projectUniqueName)) { throw new ArgumentException(Resources.Argument_Cannot_Be_Null_Or_Empty, nameof(projectUniqueName)); } if (projectRestoreInfo == null && projectRestoreInfo2 == null) { throw new ArgumentNullException(nameof(projectRestoreInfo)); } if (projectRestoreInfo != null && projectRestoreInfo2 != null) { throw new ArgumentException($"Internal error: Both {nameof(projectRestoreInfo)} and {nameof(projectRestoreInfo2)} cannot have values. Please file an issue at NuGet/Home if you see this exception."); } if (projectRestoreInfo != null) { if (projectRestoreInfo.TargetFrameworks == null) { throw new InvalidOperationException("TargetFrameworks cannot be null."); } } else { if (projectRestoreInfo2.TargetFrameworks == null) { throw new InvalidOperationException("TargetFrameworks cannot be null."); } } try { _logger.LogInformation( $"The nominate API is called for '{projectUniqueName}'."); var projectNames = ProjectNames.FromFullProjectPath(projectUniqueName); var dgSpec = ToDependencyGraphSpec(projectNames, projectRestoreInfo, projectRestoreInfo2); _projectSystemCache.AddProjectRestoreInfo(projectNames, dgSpec); // returned task completes when scheduled restore operation completes. var restoreTask = _restoreWorker.ScheduleRestoreAsync( SolutionRestoreRequest.OnUpdate(), token); return(restoreTask); } catch (OperationCanceledException) { throw; } catch (Exception e) { _logger.LogError(e.ToString()); return(Task.FromResult(false)); } }
public void AddProject_AfterAddProjectRestoreInfo_UpdatesCacheEntry() { // Arrange var target = new ProjectSystemCache(); var projectNames = new ProjectNames( fullName: @"C:\src\project\project.csproj", uniqueName: @"folder\project", shortName: "project", customUniqueName: @"folder\project"); var projectNamesFromFullPath = ProjectNames.FromFullProjectPath(@"C:\src\project\project.csproj"); var projectRestoreInfo = new DependencyGraphSpec(); target.AddProjectRestoreInfo(projectNamesFromFullPath, projectRestoreInfo); // Act target.AddProject(projectNames, vsProjectAdapter: null, nuGetProject: null); // Assert DependencyGraphSpec actual; ProjectNames names; var getPackageSpecSuccess = target.TryGetProjectRestoreInfo(projectNames.FullName, out actual); var getProjectNameSuccess = target.TryGetProjectNames(projectNames.UniqueName, out names); Assert.True(getPackageSpecSuccess); Assert.True(getProjectNameSuccess); Assert.Same(projectRestoreInfo, actual); Assert.Equal(@"folder\project", names.CustomUniqueName); }
public void AddProjectRestoreInfo_TriggersMultipleEvent_WithEventHandler_WithReset() { // Arrange var target = new ProjectSystemCache(); var projectNames = GetTestProjectNames(); var projectNamesFromFullPath = ProjectNames.FromFullProjectPath(projectNames.FullName); var projectRestoreInfo = new DependencyGraphSpec(); var eventCount = 0; target.CacheUpdated += delegate(object sender, NuGetEventArgs <string> e) { if (target.TestResetDirtyFlag()) { eventCount++; } }; // Act target.AddProjectRestoreInfo(projectNamesFromFullPath, projectRestoreInfo, additionalMessages: null); target.AddProjectRestoreInfo(projectNamesFromFullPath, projectRestoreInfo, additionalMessages: null); target.AddProjectRestoreInfo(projectNamesFromFullPath, projectRestoreInfo, additionalMessages: null); target.AddProjectRestoreInfo(projectNamesFromFullPath, projectRestoreInfo, additionalMessages: null); // Assert Assert.Equal(target.IsCacheDirty, 0); Assert.Equal(eventCount, 4); }
public void AddProjectRestoreInfo_TriggersEvent_WithEventHandler_NoReset() { // Arrange var target = new ProjectSystemCache(); var projectNames = GetTestProjectNames(); var projectNamesFromFullPath = ProjectNames.FromFullProjectPath(projectNames.FullName); var projectRestoreInfo = new DependencyGraphSpec(); var eventCount = 0; target.CacheUpdated += delegate(object sender, NuGetEventArgs <string> e) { eventCount++; }; // Act target.AddProjectRestoreInfo(projectNamesFromFullPath, projectRestoreInfo, additionalMessages: null); target.AddProjectRestoreInfo(projectNamesFromFullPath, projectRestoreInfo, additionalMessages: null); target.AddProject(projectNames, vsProjectAdapter: null, nuGetProject: null); // Assert DependencyGraphSpec actual; ProjectNames names; var getPackageSpecSuccess = target.TryGetProjectRestoreInfo(projectNames.FullName, out actual, out _); var getProjectNameSuccess = target.TryGetProjectNames(projectNames.UniqueName, out names); Assert.True(getPackageSpecSuccess); Assert.True(getProjectNameSuccess); Assert.Same(projectRestoreInfo, actual); Assert.Equal(@"folder\project", names.CustomUniqueName); // Since no listener resets the dirty flag, the cache remains dirty and only 1 event is raised. Assert.Equal(target.IsCacheDirty, 1); Assert.Equal(eventCount, 1); }
public void AddProjectRestoreInfo_AfterAddProject_UpdatesCacheEntry() { // Arrange var target = new ProjectSystemCache(); var projectNames = GetTestProjectNames(); var projectNamesFromFullPath = ProjectNames.FromFullProjectPath(projectNames.FullName); var projectRestoreInfo = new DependencyGraphSpec(); target.AddProject(projectNames, vsProjectAdapter: null, nuGetProject: null); // Act target.AddProjectRestoreInfo(projectNamesFromFullPath, projectRestoreInfo, additionalMessages: null); // Assert var getPackageSpecSuccess = target.TryGetProjectRestoreInfo(projectNames.FullName, out var actual, out _); var getProjectNameFromUniqueNameSuccess = target.TryGetProjectNames(projectNames.UniqueName, out var names1); var getProjectNameFromFullNameSuccess = target.TryGetProjectNames(projectNames.FullName, out var names2); Assert.True(getPackageSpecSuccess); Assert.True(getProjectNameFromUniqueNameSuccess); Assert.True(getProjectNameFromFullNameSuccess); Assert.Same(projectRestoreInfo, actual); Assert.Equal(@"folder\project", names1.CustomUniqueName); Assert.Equal(@"folder\project", names2.CustomUniqueName); }
public void AddProject_AfterAddProjectRestoreInfoWithProjectId_DoesNotUpdatesCacheEntryProjectId() { // Arrange var target = new ProjectSystemCache(); var projectNames = ProjectNames.FromFullProjectPath(@"C:\src\project\project.csproj"); var originalProjectSpec = new PackageSpec() { ProjectId = Guid.NewGuid().ToString(), Name = projectNames.UniqueName, RestoreMetadata = new ProjectRestoreMetadata() { ProjectUniqueName = projectNames.UniqueName } }; var projectRestoreInfo = new DependencyGraphSpec(); var nugetProject = new TestNuGetProject(projectNames.UniqueName, new List <PackageReference>()); projectRestoreInfo.AddProject(originalProjectSpec); target.AddProjectRestoreInfo(projectNames, projectRestoreInfo); // Act target.AddProject(projectNames, vsProjectAdapter: null, nuGetProject: nugetProject); // Assert var getPackageSpecSuccess = target.TryGetProjectRestoreInfo(projectNames.FullName, out var actual); // Assert getPackageSpecSuccess.Should().BeTrue(); actual.Projects.Count.Should().Be(1); actual.Projects.First().ProjectId.Should().Be(originalProjectSpec.ProjectId); }
public void AddProject_AfterAddProjectRestoreInfoWithNullProject_DoesNotUpdatesCacheEntryProjectId() { // Arrange var target = new ProjectSystemCache(); var projectNames = ProjectNames.FromFullProjectPath(@"C:\src\project\project.csproj"); var projectSpec = new PackageSpec() { ProjectId = string.Empty, Name = projectNames.UniqueName, RestoreMetadata = new ProjectRestoreMetadata() { ProjectUniqueName = projectNames.UniqueName } }; var projectRestoreInfo = new DependencyGraphSpec(); projectRestoreInfo.AddProject(projectSpec); target.AddProjectRestoreInfo(projectNames, projectRestoreInfo); // Act target.AddProject(projectNames, vsProjectAdapter: null, nuGetProject: null); // Assert var getPackageSpecSuccess = target.TryGetProjectRestoreInfo(projectNames.FullName, out var actual); // Assert getPackageSpecSuccess.Should().BeTrue(); actual.Projects.Count.Should().Be(1); actual.Projects.First().ProjectId.Should().Be(string.Empty); }
public Task <bool> NominateProjectAsync(string projectUniqueName, IVsProjectRestoreInfo projectRestoreInfo, CancellationToken token) { if (string.IsNullOrEmpty(projectUniqueName)) { throw new ArgumentException(Resources.Argument_Cannot_Be_Null_Or_Empty, nameof(projectUniqueName)); } if (projectRestoreInfo == null) { throw new ArgumentNullException(nameof(projectRestoreInfo)); } if (projectRestoreInfo.TargetFrameworks == null) { throw new InvalidOperationException("TargetFrameworks cannot be null."); } try { _logger.LogInformation( $"The nominate API is called for '{projectUniqueName}'."); var projectNames = ProjectNames.FromFullProjectPath(projectUniqueName); var dgSpec = ToDependencyGraphSpec(projectNames, projectRestoreInfo); #if DEBUG DumpProjectRestoreInfo(projectUniqueName, dgSpec); #endif _projectSystemCache.AddProjectRestoreInfo(projectNames, dgSpec); // returned task completes when scheduled restore operation completes. var restoreTask = _restoreWorker.ScheduleRestoreAsync( SolutionRestoreRequest.OnUpdate(), token); return(restoreTask); } catch (Exception e) when(e is InvalidOperationException || e is ArgumentException || e is FormatException) { _logger.LogError(e.ToString()); return(Task.FromResult(false)); } catch (Exception e) { _logger.LogError(e.ToString()); throw; } }
public void AddProjectRestoreInfo_TriggersEvent_WithEventHandler_WithReset() { // Arrange var target = new ProjectSystemCache(); var projectNames = new ProjectNames( fullName: @"C:\src\project\project.csproj", uniqueName: @"folder\project", shortName: "project", customUniqueName: @"folder\project"); var projectNamesFromFullPath = ProjectNames.FromFullProjectPath(@"C:\src\project\project.csproj"); var projectRestoreInfo = new DependencyGraphSpec(); var eventCount = 0; target.CacheUpdated += delegate(object sender, NuGetEventArgs <string> e) { if (target.TestResetDirtyFlag()) { eventCount++; } }; // Act target.AddProjectRestoreInfo(projectNamesFromFullPath, projectRestoreInfo); target.AddProject(projectNames, vsProjectAdapter: null, nuGetProject: null); // Assert DependencyGraphSpec actual; ProjectNames names; var getPackageSpecSuccess = target.TryGetProjectRestoreInfo(projectNames.FullName, out actual); var getProjectNameSuccess = target.TryGetProjectNames(projectNames.UniqueName, out names); Assert.True(getPackageSpecSuccess); Assert.True(getProjectNameSuccess); Assert.Same(projectRestoreInfo, actual); Assert.Equal(@"folder\project", names.CustomUniqueName); Assert.Equal(target.IsCacheDirty, 0); Assert.Equal(eventCount, 1); }
/// <summary> /// This is where the nominate calls for the IVs1 and IVS3 APIs combine. The reason for this method is to avoid duplication and potential issues /// The issue with this method is that it has some weird custom logging to ensure backward compatibility. It's on the implementer to ensure these calls are correct. /// <param name="projectUniqueName">projectUniqueName</param> /// <param name="projectRestoreInfo">projectRestoreInfo. Can be null</param> /// <param name="projectRestoreInfo2">proectRestoreInfo2. Can be null</param> /// <param name="token"></param> /// <remarks>Exactly one of projectRestoreInfos has to null.</remarks> /// <returns>The task that scheduled restore</returns> private Task <bool> NominateProjectAsync(string projectUniqueName, IVsProjectRestoreInfo projectRestoreInfo, IVsProjectRestoreInfo2 projectRestoreInfo2, CancellationToken token) { if (string.IsNullOrEmpty(projectUniqueName)) { throw new ArgumentException(Resources.Argument_Cannot_Be_Null_Or_Empty, nameof(projectUniqueName)); } if (projectRestoreInfo == null && projectRestoreInfo2 == null) { throw new ArgumentNullException(nameof(projectRestoreInfo)); } if (projectRestoreInfo != null && projectRestoreInfo2 != null) { throw new ArgumentException($"Internal error: Both {nameof(projectRestoreInfo)} and {nameof(projectRestoreInfo2)} cannot have values. Please file an issue at NuGet/Home if you see this exception."); } if (projectRestoreInfo != null) { if (projectRestoreInfo.TargetFrameworks == null) { throw new InvalidOperationException("TargetFrameworks cannot be null."); } } else { if (projectRestoreInfo2.TargetFrameworks == null) { throw new InvalidOperationException("TargetFrameworks cannot be null."); } } try { _logger.LogInformation( $"The nominate API is called for '{projectUniqueName}'."); var projectNames = ProjectNames.FromFullProjectPath(projectUniqueName); DependencyGraphSpec dgSpec; IReadOnlyList <IAssetsLogMessage> nominationErrors = null; try { dgSpec = ToDependencyGraphSpec(projectNames, projectRestoreInfo, projectRestoreInfo2); } catch (Exception e) { var restoreLogMessage = RestoreLogMessage.CreateError(NuGetLogCode.NU1105, string.Format(Resources.NU1105, projectNames.ShortName, e.Message)); restoreLogMessage.LibraryId = projectUniqueName; nominationErrors = new List <IAssetsLogMessage>() { AssetsLogMessage.Create(restoreLogMessage) }; var projectDirectory = Path.GetDirectoryName(projectUniqueName); string projectIntermediatePath = projectRestoreInfo == null ? projectRestoreInfo2.BaseIntermediatePath : projectRestoreInfo.BaseIntermediatePath; var dgSpecOutputPath = GetProjectOutputPath(projectDirectory, projectIntermediatePath); dgSpec = CreateMinimalDependencyGraphSpec(projectUniqueName, dgSpecOutputPath); } _projectSystemCache.AddProjectRestoreInfo(projectNames, dgSpec, nominationErrors); // returned task completes when scheduled restore operation completes. var restoreTask = _restoreWorker.ScheduleRestoreAsync( SolutionRestoreRequest.OnUpdate(), token); return(restoreTask); } catch (OperationCanceledException) { throw; } catch (Exception e) { _logger.LogError(e.ToString()); TelemetryUtility.EmitException(nameof(VsSolutionRestoreService), nameof(NominateProjectAsync), e); return(Task.FromResult(false)); } }