public void DuplicateInputsAndOutputsMergePredictedBys() { var predictors = new IProjectPredictor[] { new MockPredictor( new[] { @"common\inputFile" }, new[] { @"common\inputDirectory" }, new[] { @"common\outputFile" }, new[] { @"common\outputDirectory" }), new MockPredictor2( new[] { @"common\inputFile" }, new[] { @"common\inputDirectory" }, new[] { @"common\outputFile" }, new[] { @"common\outputDirectory" }), }; var executor = new ProjectPredictionExecutor(predictors); var project = TestHelpers.CreateProjectInstanceFromRootElement(ProjectRootElement.Create()); ProjectPredictions predictions = executor.PredictInputsAndOutputs(project); predictions.AssertPredictions( project, new[] { new PredictedItem(@"common\inputFile", "MockPredictor", "MockPredictor2"), }, new[] { new PredictedItem(@"common\inputDirectory", "MockPredictor", "MockPredictor2"), }, new[] { new PredictedItem(@"common\outputFile", "MockPredictor", "MockPredictor2"), }, new[] { new PredictedItem(@"common\outputDirectory", "MockPredictor", "MockPredictor2"), }); }
public void DistinctInputsAndOutputsAreAggregated() { /* * Missed value in the input files: * PredictedItem: 1\inputFile; PredictedBy=MockPredictor * from among actual list * PredictedItem: E:\MSBuildPrediction\src\BuildPredictionTests\bin\Debug\net472\2\inputFile; PredictedBy=MockPredictor2:: PredictedItem: E:\MSBuildPrediction\src\BuildPredictionTests\bin\Debug\net472\1\inputFile; PredictedBy=MockPredictor */ var predictors = new IProjectPredictor[] { new MockPredictor( new[] { @"1\inputFile" }, new[] { @"1\inputDirectory" }, new[] { @"1\outputFile" }, new[] { @"1\outputDirectory" }), new MockPredictor2( new[] { @"2\inputFile" }, new[] { @"2\inputDirectory" }, new[] { @"2\outputFile" }, new[] { @"2\outputDirectory" }), }; var executor = new ProjectPredictionExecutor(predictors); var project = TestHelpers.CreateProjectInstanceFromRootElement(ProjectRootElement.Create()); ProjectPredictions predictions = executor.PredictInputsAndOutputs(project); predictions.AssertPredictions( project, new[] { new PredictedItem(@"1\inputFile", "MockPredictor"), new PredictedItem(@"2\inputFile", "MockPredictor2"), }, new[] { new PredictedItem(@"1\inputDirectory", "MockPredictor"), new PredictedItem(@"2\inputDirectory", "MockPredictor2"), }, new[] { new PredictedItem(@"1\outputFile", "MockPredictor"), new PredictedItem(@"2\outputFile", "MockPredictor2"), }, new[] { new PredictedItem(@"1\outputDirectory", "MockPredictor"), new PredictedItem(@"2\outputDirectory", "MockPredictor2"), }); }
public static void AssertPredictions( this ProjectPredictions predictions, string rootDir, IReadOnlyCollection <PredictedItem> expectedInputFiles, IReadOnlyCollection <PredictedItem> expectedInputDirectories, IReadOnlyCollection <PredictedItem> expectedOutputFiles, IReadOnlyCollection <PredictedItem> expectedOutputDirectories) => AssertPredictions( predictions, expectedInputFiles.MakeAbsolute(rootDir), expectedInputDirectories.MakeAbsolute(rootDir), expectedOutputFiles.MakeAbsolute(rootDir), expectedOutputDirectories.MakeAbsolute(rootDir));
public static void AssertPredictions( this ProjectPredictions predictions, ProjectInstance projectInstance, IReadOnlyCollection <PredictedItem> expectedInputFiles, IReadOnlyCollection <PredictedItem> expectedInputDirectories, IReadOnlyCollection <PredictedItem> expectedOutputFiles, IReadOnlyCollection <PredictedItem> expectedOutputDirectories) => AssertPredictions( predictions, projectInstance.Directory, expectedInputFiles, expectedInputDirectories, expectedOutputFiles, expectedOutputDirectories);
private (bool, string) IsBuildUpToDate(ProjectInstance projectInstance, ProjectPredictions predictions) { HashSet <string> inputs = GetAllFiles(predictions.InputFiles, predictions.InputDirectories); var outputs = new HashSet <string>(StringComparer.OrdinalIgnoreCase); AddCustomInputs(inputs, projectInstance); AddCustomOutputs(outputs, projectInstance); // The prediction library can sometimes flag intermediate files as inputs. // For example, if a file was copied to $(OutDir) and then copied elsewhere, // it'll see that file as an input because it was the input to the 2nd copy. // To avoid this, we'll prune the input list, removing everything from $(OutDir). string outDir = projectInstance.GetPropertyValue("OutDir"); inputs.RemoveWhere((input) => input.StartsWith(outDir, StringComparison.OrdinalIgnoreCase)); _logger.LogVerbose($"Removing inputs residing in OutDir ({outDir})..."); var context = new ProjectBuildCheckContext() { Logger = _logger, Instance = projectInstance, Predictions = predictions, Inputs = inputs, Outputs = outputs, TimeStampCache = new Dictionary <string, DateTime>(StringComparer.OrdinalIgnoreCase), VerboseOutput = _verboseOutput }; // Log predicted inputs and outputs. _logger.LogVerbose(string.Empty); _logger.LogVerbose("Predicted Inputs:"); foreach (string input in inputs.OrderBy(i => i)) { _logger.LogVerbose($" {input}"); } _logger.LogVerbose(string.Empty); _logger.LogVerbose("Predicted Outputs:"); foreach (string output in outputs.OrderBy(i => i)) { _logger.LogVerbose($" {output}"); } // All checks must pass for the build to be up to date. string failureMessage = string.Empty; return(_checkProvider.GetBuildChecks().All(buildCheck => buildCheck.Check(context, out failureMessage)), failureMessage); }
/// <summary> /// Performs analysis on the given project to determine if the project is up to date or not. /// </summary> /// <param name="fullPathToProjectFile">The full path to the project file.</param> /// <returns>True, if all project checks pass and the project is up to date. Else, false.</returns> public (bool, string) IsBuildUpToDate(string fullPathToProjectFile) { _logger.Log($"Checking if project '{ fullPathToProjectFile }' is up to date."); // Get project objects (Project project, ProjectInstance projectInstance) = GetProjectObjects(fullPathToProjectFile); // Get predictions for project ProjectPredictions predictions = GetProjectPredictions(project); (bool projectBuildIsUpToDate, string failureMessage) = IsBuildUpToDate(projectInstance, predictions); _logger.Log(projectBuildIsUpToDate ? "Build is up to date." : "Build is not up to date."); return(projectBuildIsUpToDate, failureMessage); }
private static void AssertPredictions( this ProjectPredictions predictions, IReadOnlyCollection <PredictedItem> expectedInputFiles, IReadOnlyCollection <PredictedItem> expectedInputDirectories, IReadOnlyCollection <PredictedItem> expectedOutputFiles, IReadOnlyCollection <PredictedItem> expectedOutputDirectories) { Assert.NotNull(predictions); if (expectedInputFiles == null) { Assert.Equal(0, predictions.InputFiles.Count); } else { CheckCollection(expectedInputFiles, predictions.InputFiles, PredictedItemComparer.Instance, "input files"); } if (expectedInputDirectories == null) { Assert.Equal(0, predictions.InputDirectories.Count); } else { CheckCollection(expectedInputDirectories, predictions.InputDirectories, PredictedItemComparer.Instance, "input directories"); } if (expectedOutputFiles == null) { Assert.Equal(0, predictions.OutputFiles.Count); } else { CheckCollection(expectedOutputFiles, predictions.OutputFiles, PredictedItemComparer.Instance, "output files"); } if (expectedOutputDirectories == null) { Assert.Equal(0, predictions.OutputDirectories.Count); } else { CheckCollection(expectedOutputDirectories, predictions.OutputDirectories, PredictedItemComparer.Instance, "output directories"); } }
public void EmptyPredictionsResultInEmptyAggregateResult() { var predictors = new IProjectPredictor[] { new MockPredictor(null, null, null, null), new MockPredictor(null, null, null, null), }; var executor = new ProjectPredictionExecutor(predictors); var project = TestHelpers.CreateProjectInstanceFromRootElement(ProjectRootElement.Create()); ProjectPredictions predictions = executor.PredictInputsAndOutputs(project); Assert.NotNull(predictions); Assert.Equal(0, predictions.InputFiles.Count); Assert.Equal(0, predictions.InputDirectories.Count); Assert.Equal(0, predictions.OutputFiles.Count); Assert.Equal(0, predictions.OutputDirectories.Count); }
public static void AssertNoPredictions(this ProjectPredictions predictions) => predictions.AssertPredictions(null, null, null, null);