示例#1
0
        /// <summary>
        /// Adds the specified build result to the cache
        /// </summary>
        /// <param name="result">The result to add.</param>
        public void AddResult(BuildResult result)
        {
            lock (_resultsByConfiguration)
            {
                if (_resultsByConfiguration.ContainsKey(result.ConfigurationId))
                {
                    if (Object.ReferenceEquals(_resultsByConfiguration[result.ConfigurationId], result))
                    {
                        // Merging results would be meaningless as we would be merging the object with itself.
                        return;
                    }

                    _resultsByConfiguration[result.ConfigurationId].MergeResults(result);
                }
                else
                {
                    // Note that we are not making a copy here.  This is by-design.  The TargetBuilder uses this behavior
                    // to ensure that re-entering a project will be able to see all previously built targets and avoid
                    // building them again.
                    if (!_resultsByConfiguration.TryAdd(result.ConfigurationId, result))
                    {
                        ErrorUtilities.ThrowInternalError("Failed to add result for configuration {0}", result.ConfigurationId);
                    }
                }
            }
        }
示例#2
0
 private BuildResult MapBuildResult(string project, Microsoft.Build.Execution.BuildResult buildResult)
 {
     var escapedProject = EscapingUtilities.Escape(project);
     return new BuildResult
     {
         Project = project,
         Exception = buildResult.Exception,
         CircularDependency = buildResult.CircularDependency,
         ConfigurationId = buildResult.ConfigurationId,
         GlobalRequestId = buildResult.GlobalRequestId,
         NodeRequestId = buildResult.NodeRequestId,
         OverallResult = buildResult.OverallResult,
         ParentGlobalRequestId = buildResult.ParentGlobalRequestId,
         ResultsByTarget = new ResultsByTarget(buildResult.ResultsByTarget.ToDictionary(x => x.Key, x => new TargetResult
         {
             Name = x.Key,
             Exception = x.Value.Exception,
             ResultCode = x.Value.ResultCode,
             Items = x.Value.Items.Cast<ITaskItem2>().Select(
                 y => new TaskItem(
                     y.EvaluatedIncludeEscaped,
                     escapedProject,
                     ToGeneric(y.CloneCustomMetadataEscaped())))
                 .ToArray()
         }))
     };
 }
        public void TestSimpleBuildRequest()
        {
            BuildRequestConfiguration configuration = CreateTestProject(1);
            try
            {
                TestTargetBuilder targetBuilder = (TestTargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
                IConfigCache configCache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);

                configCache.AddConfiguration(configuration);

                BuildRequest request = CreateNewBuildRequest(1, new string[1] { "target1" });
                BuildRequestEntry entry = new BuildRequestEntry(request, configuration);
                BuildResult result = new BuildResult(request);
                result.AddResultsForTarget("target1", GetEmptySuccessfulTargetResult());
                targetBuilder.SetResultsToReturn(result);

                _requestBuilder.BuildRequest(GetNodeLoggingContext(), entry);
                WaitForEvent(_buildRequestCompletedEvent, "Build Request Completed");
                Assert.Equal(BuildRequestEntryState.Complete, entry.State);
                Assert.Equal(entry, _buildRequestCompleted_Entry);
                Assert.Equal(BuildResultCode.Success, _buildRequestCompleted_Entry.Result.OverallResult);
            }
            finally
            {
                DeleteTestProject(configuration);
            }
        }
示例#4
0
        public void SetUp()
        {
            LoggingServiceFactory loggingFactory = new LoggingServiceFactory(LoggerMode.Synchronous, 1);

            _loggingService = loggingFactory.CreateInstance(BuildComponentType.LoggingService) as LoggingService;

            _customLogger = new MyCustomLogger();
            _mockHost = new MockHost();
            _mockHost.LoggingService = _loggingService;

            _loggingService.RegisterLogger(_customLogger);
            _elementLocation = ElementLocation.Create("MockFile", 5, 5);

            BuildRequest buildRequest = new BuildRequest(1 /* submissionId */, 1, 1, new List<string>(), null, BuildEventContext.Invalid, null);
            BuildRequestConfiguration configuration = new BuildRequestConfiguration(1, new BuildRequestData("Nothing", new Dictionary<string, string>(), "4.0", new string[0], null), "2.0");

            configuration.Project = new ProjectInstance(ProjectRootElement.Create());

            BuildRequestEntry entry = new BuildRequestEntry(buildRequest, configuration);

            BuildResult buildResult = new BuildResult(buildRequest, false);
            buildResult.AddResultsForTarget("Build", new TargetResult(new TaskItem[] { new TaskItem("IamSuper", configuration.ProjectFullPath) }, TestUtilities.GetSkippedResult()));
            _mockRequestCallback = new MockIRequestBuilderCallback(new BuildResult[] { buildResult });
            entry.Builder = (IRequestBuilder)_mockRequestCallback;

            _taskHost = new TaskHost(_mockHost, entry, _elementLocation, null /*Dont care about the callback either unless doing a build*/);
            _taskHost.LoggingContext = new TaskLoggingContext(_loggingService, BuildEventContext.Invalid);
        }
        /// <summary>
        /// Checks that a SonarQubeSetting does not exist
        /// </summary>
        public static void AssertAnalysisSettingDoesNotExist(BuildResult actualResult, string settingName)
        {
            Assert.IsNotNull(actualResult.ProjectStateAfterBuild, "Test error: ProjectStateAfterBuild should not be null");

            IEnumerable<ProjectItemInstance> matches = actualResult.ProjectStateAfterBuild.GetItemsByItemTypeAndEvaluatedInclude(BuildTaskConstants.SettingItemName, settingName);

            Assert.AreEqual(0, matches.Count(), "Not expected SonarQubeSetting with include value of '{0}' to exist. Actual occurences: {1}", settingName, matches.Count());
        }
示例#6
0
 public void TestConstructorBad()
 {
     Assert.Throws<InternalErrorException>(() =>
     {
         BuildResult result = new BuildResult(null);
     }
    );
 }
示例#7
0
        public void TestConfigurationId()
        {
            BuildRequest request = CreateNewBuildRequest(-1, new string[0]);
            BuildResult result = new BuildResult(request);
            Assert.AreEqual(-1, result.ConfigurationId);

            BuildRequest request2 = CreateNewBuildRequest(1, new string[0]);
            BuildResult result2 = new BuildResult(request2);
            Assert.AreEqual(1, result2.ConfigurationId);
        }
        /// <summary>
        /// Checks that building the specified target produced the expected result.
        /// </summary>
        public static void AssertExpectedTargetOutput(BuildResult result, string target, BuildResultCode resultCode)
        {
            DumpTargetResult(result, target);

            TargetResult targetResult;
            if (!result.ResultsByTarget.TryGetValue(target, out targetResult))
            {
                Assert.Inconclusive(@"Could not find result for target ""{0}""", target);
            }
            Assert.AreEqual<BuildResultCode>(resultCode, result.OverallResult, "Unexpected build result");
        }
示例#9
0
        public void TestAddAndRetrieveResults()
        {
            ResultsCache cache = new ResultsCache();
            BuildRequest request = new BuildRequest(1 /* submissionId */, 0, 1, new string[1] { "testTarget" }, null, BuildEventContext.Invalid, null); BuildResult result = new BuildResult(request);
            result.AddResultsForTarget("testTarget", TestUtilities.GetEmptyFailingTargetResult());
            cache.AddResult(result);

            BuildResult retrievedResult = cache.GetResultForRequest(request);

            Assert.True(AreResultsIdentical(result, retrievedResult));
        }
示例#10
0
		// FIXME:
		// While we are not faced to implement those features, there are some modern task execution requirements.
		//
		// This will have to be available for "out of process" nodes (see NodeAffinity).
		// NodeAffinity is set per project file at BuildManager.HostServices.
		// When NodeAffinity is set to OutOfProc, it should probably launch different build host
		// that runs separate build tasks. (.NET has MSBuildTaskHost.exe which I guess is about that.)
		//
		// Also note that the complete implementation has to support LoadInSeparateAppDomainAttribute
		// (which is most likely derived from AppDomainIsolatedBuildTask) that marks a task to run
		// in separate AppDomain.
		//
		public void BuildProject (Func<bool> checkCancel, BuildResult result, ProjectInstance project, IEnumerable<string> targetNames, IDictionary<string,string> globalProperties, IDictionary<string,string> targetOutputs, string toolsVersion)
		{
			if (toolsVersion == null)
				throw new ArgumentNullException ("toolsVersion");
			
			var parameters = submission.BuildManager.OngoingBuildParameters;
			var toolset = parameters.GetToolset (toolsVersion);
			if (toolset == null)
				throw new InvalidOperationException (string.Format ("Toolset version '{0}' was not resolved to valid toolset", toolsVersion));
			LogMessageEvent (new BuildMessageEventArgs (string.Format ("Using Toolset version {0}.", toolsVersion), null, null, MessageImportance.Low));
			var buildTaskFactory = new BuildTaskFactory (BuildTaskDatabase.GetDefaultTaskDatabase (toolset), new BuildTaskDatabase (this, submission.BuildRequest.ProjectInstance));
			BuildProject (new InternalBuildArguments () { CheckCancel = checkCancel, Result = result, Project = project, TargetNames = targetNames, GlobalProperties = globalProperties, TargetOutputs = targetOutputs, ToolsVersion = toolsVersion, BuildTaskFactory = buildTaskFactory });
		}
        /// <summary>
        /// Checks that the expected number of ItemType entries exist
        /// </summary>
        public static void AssertExpectedItemGroupCount(BuildResult actualResult, string itemType, int expectedCount)
        {
            Assert.IsNotNull(actualResult.ProjectStateAfterBuild, "Test error: ProjectStateAfterBuild should not be null");

            IEnumerable<ProjectItemInstance> matches = actualResult.ProjectStateAfterBuild.GetItems(itemType);

            BuildUtilities.LogMessage("Analyzers:");
            foreach(ProjectItemInstance item in matches)
            {
                BuildUtilities.LogMessage("\t{0}", item.EvaluatedInclude);
            }

            Assert.AreEqual(expectedCount, matches.Count(), "Unexpected number of '{0}' items", itemType);
        }
        public void TestSimpleStateProgression()
        {
            // Start in Ready
            BuildRequest request = CreateNewBuildRequest(1, new string[1] { "foo" });
            BuildRequestConfiguration config = new BuildRequestConfiguration(1, new BuildRequestData("foo", new Dictionary<string, string>(), "foo", new string[0], null), "2.0");
            BuildRequestEntry entry = new BuildRequestEntry(request, config);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Ready);
            Assert.AreEqual(entry.Request, request);
            Assert.IsNull(entry.Result);

            // Move to active.  Should not be any results yet.
            IDictionary<int, BuildResult> results = entry.Continue();
            Assert.AreEqual(entry.State, BuildRequestEntryState.Active);
            Assert.IsNull(entry.Result);
            Assert.IsNull(results);

            // Wait for results, move to waiting.
            BuildRequest waitingRequest = CreateNewBuildRequest(2, new string[1] { "bar" });
            entry.WaitForResult(waitingRequest);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Waiting);
            Assert.AreEqual(entry.Request, request);
            Assert.IsNull(entry.Result);

            // Provide the results, move to ready.
            BuildResult requiredResult = new BuildResult(waitingRequest);
            requiredResult.AddResultsForTarget("bar", TestUtilities.GetEmptySucceedingTargetResult());
            entry.ReportResult(requiredResult);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Ready);
            Assert.AreEqual(entry.Request, request);
            Assert.IsNull(entry.Result);

            // Continue the build, move to active.
            results = entry.Continue();
            Assert.AreEqual(entry.State, BuildRequestEntryState.Active);
            Assert.IsNull(entry.Result);
            Assert.AreEqual(results.Count, 1);
            Assert.IsTrue(results.ContainsKey(requiredResult.NodeRequestId));
            Assert.AreEqual(results[requiredResult.NodeRequestId], requiredResult);

            // Complete the build, move to completed.
            BuildResult result = new BuildResult(request);
            result.AddResultsForTarget("foo", TestUtilities.GetEmptySucceedingTargetResult());
            entry.Complete(result);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Complete);
            Assert.IsNotNull(entry.Result);
            Assert.AreEqual(entry.Result, result);
        }
示例#13
0
        public void TestAddAndRetrieveResultsByConfiguration()
        {
            ResultsCache cache = new ResultsCache();
            BuildRequest request = new BuildRequest(1 /* submissionId */, 0, 1, new string[1] { "testTarget" }, null, BuildEventContext.Invalid, null);
            BuildResult result = new BuildResult(request);
            result.AddResultsForTarget("testTarget", TestUtilities.GetEmptyFailingTargetResult());
            cache.AddResult(result);

            request = new BuildRequest(1 /* submissionId */, 0, 1, new string[1] { "otherTarget" }, null, BuildEventContext.Invalid, null);
            result = new BuildResult(request);
            result.AddResultsForTarget("otherTarget", TestUtilities.GetEmptySucceedingTargetResult());
            cache.AddResult(result);

            BuildResult retrievedResult = cache.GetResultsForConfiguration(1);

            Assert.True(retrievedResult.HasResultsForTarget("testTarget"));
            Assert.True(retrievedResult.HasResultsForTarget("otherTarget"));
        }
示例#14
0
		internal BuildResult InternalExecute ()
		{
			BuildResult = new BuildResult () { SubmissionId = SubmissionId };
			try {
				var engine = new BuildEngine4 (this);
				string toolsVersion = request.ExplicitlySpecifiedToolsVersion ?? request.ProjectInstance.ToolsVersion ?? BuildManager.OngoingBuildParameters.DefaultToolsVersion;
				var outputs = new Dictionary<string,string> ();
				engine.BuildProject (() => is_canceled, BuildResult, request.ProjectInstance, request.TargetNames, BuildManager.OngoingBuildParameters.GlobalProperties, outputs, toolsVersion);
			} catch (Exception ex) {
				BuildResult.Exception = ex;
				BuildResult.OverallResult = BuildResultCode.Failure;
			}
			is_completed = true;
			if (callback != null)
				callback (this);
			wait_handle.Set ();
			return BuildResult;
		}
示例#15
0
		public void MergeResults (BuildResult results)
		{
			if (ConfigurationId != results.ConfigurationId)
				throw new InvalidOperationException ("Argument BuildResults have inconsistent ConfigurationId.");
			if (GlobalRequestId != results.GlobalRequestId)
				throw new InvalidOperationException ("Argument BuildResults have inconsistent GlobalRequestId.");
			if (NodeRequestId != results.NodeRequestId)
				throw new InvalidOperationException ("Argument BuildResults have inconsistent NodeRequestId.");
			if (ParentGlobalRequestId != results.ParentGlobalRequestId)
				throw new InvalidOperationException ("Argument BuildResults have inconsistent ParentGlobalRequestId.");
			if (SubmissionId != results.SubmissionId)
				throw new InvalidOperationException ("Argument BuildResults have inconsistent SubmissionId.");
			
			CircularDependency |= results.CircularDependency;
			Exception = Exception ?? results.Exception;
			foreach (var p in results.ResultsByTarget)
				ResultsByTarget.Add (p.Key, p.Value);
		}
        /// <summary>
        /// Writes the build and target output to the output stream
        /// </summary>
        public static void DumpTargetResult(BuildResult result, string target)
        {
            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            BuildUtilities.LogMessage("Overall build result: {0}", result.OverallResult.ToString());

            TargetResult targetResult;
            if (!result.ResultsByTarget.TryGetValue(target, out targetResult))
            {
                BuildUtilities.LogMessage(@"Could not find result for target ""{0}""", target);
            }
            else
            {
                BuildUtilities.LogMessage(@"Results for target ""{0}""", target);
                BuildUtilities.LogMessage("\tTarget exception: {0}", targetResult.Exception == null ? "{null}" : targetResult.Exception.Message);
                BuildUtilities.LogMessage("\tTarget result: {0}", targetResult.ResultCode.ToString());
            }
        }
        /// <summary>
        /// Checks whether there is a single "SonarQubeSetting" item with the expected name and setting value
        /// </summary>
        public static void AssertExpectedAnalysisSetting(BuildResult actualResult, string settingName, string expectedValue)
        {
            /* The equivalent XML would look like this:
            <ItemGroup>
              <SonarQubeSetting Include="settingName">
                <Value>expectedValue</Value
              </SonarQubeSetting>
            </ItemGroup>
            */

            Assert.IsNotNull(actualResult.ProjectStateAfterBuild, "Test error: ProjectStateAfterBuild should not be null");

            IEnumerable<ProjectItemInstance> matches = actualResult.ProjectStateAfterBuild.GetItemsByItemTypeAndEvaluatedInclude(BuildTaskConstants.SettingItemName, settingName);

            Assert.AreNotEqual(0, matches.Count(), "Expected SonarQubeSetting with include value of '{0}' does not exist", settingName);
            Assert.AreEqual(1, matches.Count(), "Only expecting one SonarQubeSetting with include value of '{0}' to exist", settingName);

            ProjectItemInstance item = matches.Single();
            string value = item.GetMetadataValue(BuildTaskConstants.SettingValueMetadataName);

            Assert.AreEqual(expectedValue, value, "SonarQubeSetting with include value '{0}' does not have the expected value", settingName);
        }
示例#18
0
        public void Clone()
        {
            BuildRequest request = CreateNewBuildRequest(1, new string[0]);
            BuildResult result1 = new BuildResult(request);
            result1.ResultsByTarget.Add("FOO", TestUtilities.GetEmptySucceedingTargetResult());
            Assert.IsTrue(result1.ResultsByTarget.ContainsKey("foo")); // test comparer

            BuildResult result2 = result1.Clone();

            result1.ResultsByTarget.Add("BAR", TestUtilities.GetEmptySucceedingTargetResult());
            Assert.IsTrue(result1.ResultsByTarget.ContainsKey("foo")); // test comparer
            Assert.IsTrue(result1.ResultsByTarget.ContainsKey("bar"));

            Assert.AreEqual(result1.SubmissionId, result2.SubmissionId);
            Assert.AreEqual(result1.ConfigurationId, result2.ConfigurationId);
            Assert.AreEqual(result1.GlobalRequestId, result2.GlobalRequestId);
            Assert.AreEqual(result1.ParentGlobalRequestId, result2.ParentGlobalRequestId);
            Assert.AreEqual(result1.NodeRequestId, result2.NodeRequestId);
            Assert.AreEqual(result1.CircularDependency, result2.CircularDependency);
            Assert.AreEqual(result1.ResultsByTarget["foo"], result2.ResultsByTarget["foo"]);
            Assert.AreEqual(result1.OverallResult, result2.OverallResult);
        }
        public void BuildAndAnalyze()
        {
            var globalProps = new Dictionary<string, string> {
                {"VisualStudioVersion","12.0"}
            };
            pc = new ProjectCollection(globalProps);

            var diagLogger = new DiagnosticXmlLogger(this);
            diagLogger.LogFile = _logFilepath;

            project = pc.LoadProject(_projectFilepath, "12.0");
            projInst = project.CreateProjectInstance();
            buildManager = new BuildManager();
            var buildParams = new BuildParameters();
            buildParams.Loggers = new ILogger[] { diagLogger };
            buildManager.BeginBuild(buildParams);

            var brd = new BuildRequestData(projInst, _targets, null, BuildRequestDataFlags.ReplaceExistingProjectInstance);
            submission = buildManager.PendBuildRequest(brd);
            buildResult = submission.Execute();

            buildManager.EndBuild();
        }
示例#20
0
        /// <summary>
        /// Logs the project started/finished pair for projects which are skipped entirely because all
        /// of their results are available in the cache.
        /// </summary>
        internal void LogRequestHandledFromCache(BuildRequest request, BuildRequestConfiguration configuration, BuildResult result)
        {
            ProjectLoggingContext projectLoggingContext = LogProjectStarted(request, configuration);

            // When pulling a request from the cache, we want to make sure we log a task skipped message for any targets which 
            // were used to build the request including default and inital targets.
            foreach (string target in configuration.GetTargetsUsedToBuildRequest(request))
            {
                projectLoggingContext.LogComment
                    (
                        MessageImportance.Low,
                        result[target].ResultCode == TargetResultCode.Failure ? "TargetAlreadyCompleteFailure" : "TargetAlreadyCompleteSuccess",
                        target
                    );

                if (result[target].ResultCode == TargetResultCode.Failure)
                {
                    break;
                }
            }

            projectLoggingContext.LogProjectFinished(result.OverallResult == BuildResultCode.Success);
        }
 private void AssertExpectedAnalyzersExists(BuildResult result, params string[] analyzerFilePaths)
 {
     this.DumpAnalyzerLists(result, analyzerFilePaths);
     foreach (string filePath in analyzerFilePaths)
     {
         BuildAssertions.AssertSingleItemExists(result, TargetProperties.AnalyzerItemType, filePath);
     }
     BuildAssertions.AssertExpectedItemGroupCount(result, TargetProperties.AnalyzerItemType, analyzerFilePaths.Length);
 }
 private static void AssertExpectedAnalysisProperties(BuildResult result, string expectedErrorLog, string expectedResolvedRuleset)
 {
     // Check the ruleset and error log are not set
     BuildAssertions.AssertExpectedPropertyValue(result.ProjectStateAfterBuild, TargetProperties.ErrorLog, expectedErrorLog);
     BuildAssertions.AssertExpectedPropertyValue(result.ProjectStateAfterBuild, TargetProperties.ResolvedCodeAnalysisRuleset, expectedResolvedRuleset);
 }
 private static void AssertCodeAnalysisIsDisabled(BuildResult result)
 {
     // Check the ruleset and error log are not set
     AssertExpectedAnalysisProperties(result, string.Empty, string.Empty);
 }
示例#24
0
        private string ResolveTargetPath(BuildResult result)
        {
            string targetPath = null;
            TargetResult targetResult;
            if (result.ResultsByTarget.TryGetValue("Build", out targetResult))
            {
                if (targetResult.Items.Any())
                {
                    targetPath = targetResult.Items.First().ItemSpec;
                }
            }

            return targetPath ?? ResolveTargetPath();
        }
示例#25
0
        /// <summary>
        /// This reports a result for a request on which this entry was waiting.
        /// PERF: Once we have fixed up all the result reporting, we can probably
        /// optimize this.  See the comment in BuildRequestEngine.ReportBuildResult.
        /// </summary>
        /// <param name="result">The result for the request.</param>
        public void ReportResult(BuildResult result)
        {
            lock (_dataMonitor)
            {
                ErrorUtilities.VerifyThrowArgumentNull(result, "result");
                ErrorUtilities.VerifyThrow(_state == BuildRequestEntryState.Waiting || _outstandingRequests == null, "Entry must be in the Waiting state to report results, or we must have flushed our requests due to an error. Config: {0} State: {1} Requests: {2}", _requestConfiguration.ConfigurationId, _state, _outstandingRequests != null);

                // If the matching request is in the issue list, remove it so we don't try to ask for it to be built.
                if (_requestsToIssue != null)
                {
                    for (int i = 0; i < _requestsToIssue.Count; i++)
                    {
                        if (_requestsToIssue[i].NodeRequestId == result.NodeRequestId)
                        {
                            _requestsToIssue.RemoveAt(i);
                            if (_requestsToIssue.Count == 0)
                            {
                                _requestsToIssue = null;
                            }

                            break;
                        }
                    }
                }

                // If this result is for the request we were blocked on locally (target re-entrancy) clear out our blockage.
                bool addResults = false;
                if (_blockingGlobalRequestId == result.GlobalRequestId)
                {
                    _blockingGlobalRequestId = BuildRequest.InvalidGlobalRequestId;
                    if (_outstandingRequests == null)
                    {
                        ErrorUtilities.VerifyThrow(result.CircularDependency, "Received result for target in progress and it wasn't a circular dependency error.");
                        addResults = true;
                    }
                }

                // We could be in the waiting state but waiting on configurations instead of results, or we received a circular dependency
                // result, which blows away everything else we were waiting on.
                if (_outstandingRequests != null)
                {
                    _outstandingRequests.Remove(result.NodeRequestId);

                    // If we wish to implement behavior where we stop building after the first failing request, then check for 
                    // overall results being failure rather than just circular dependency. Sync with BasicScheduler.ReportResult and
                    // BasicScheduler.ReportRequestBlocked.
                    if (result.CircularDependency || (_outstandingRequests.Count == 0 && (_unresolvedConfigurations == null || _unresolvedConfigurations.Count == 0)))
                    {
                        _outstandingRequests = null;
                        _unresolvedConfigurations = null;

                        // If we are in the middle of IssueBuildRequests and collecting requests (and cached results), one of those results
                        // was a failure.  As a result, this entry will fail, and submitting further requests from it would be pointless.
                        _requestsToIssue = null;
                        _unresolvedConfigurationsToIssue = null;
                    }

                    addResults = true;
                }

                if (addResults)
                {
                    // Update the local results record
                    _outstandingResults = _outstandingResults ?? new Dictionary<int, BuildResult>();
                    ErrorUtilities.VerifyThrow(!_outstandingResults.ContainsKey(result.NodeRequestId), "Request already contains results.");
                    _outstandingResults.Add(result.NodeRequestId, result);
                }

                // If we are out of outstanding requests, we are ready to continue.
                if (_outstandingRequests == null && _unresolvedConfigurations == null && _blockingGlobalRequestId == BuildRequest.InvalidGlobalRequestId)
                {
                    ChangeState(BuildRequestEntryState.Ready);
                }
            }
        }
示例#26
0
        /// <summary>
        /// Constructs a new build result with existing results, but associated with the specified request.
        /// </summary>
        /// <param name="request">The build request with which these results should be associated.</param>
        /// <param name="existingResults">The existing results, if any.</param>
        /// <param name="targetNames">The list of target names that are the subset of results that should be returned.</param>
        /// <param name="additionalTargetsToCheck">The additional targets that need to be taken into account when computing the overall result, if any.</param>
        /// <param name="exception">The exception, if any</param>
        internal BuildResult(BuildRequest request, BuildResult existingResults, string[] targetNames, List <string> additionalTargetsToCheck, Exception exception)
        {
            ErrorUtilities.VerifyThrow(request != null, "Must specify a request.");
            _submissionId          = request.SubmissionId;
            _configurationId       = request.ConfigurationId;
            _globalRequestId       = request.GlobalRequestId;
            _parentGlobalRequestId = request.ParentGlobalRequestId;
            _nodeRequestId         = request.NodeRequestId;
            _circularDependency    = false;

            if (existingResults == null)
            {
                _requestException  = exception;
                _resultsByTarget   = CreateTargetResultDictionary(0);
                _baseOverallResult = true;
            }
            else
            {
                _requestException = exception ?? existingResults._requestException;

                _resultsByTarget = targetNames == null ? existingResults._resultsByTarget : CreateTargetResultDictionaryWithContents(existingResults, targetNames);

                if (existingResults.OverallResult == BuildResultCode.Success || (additionalTargetsToCheck == null || additionalTargetsToCheck.Count == 0))
                {
                    // If we know for a fact that all of the existing results succeeded, then by definition we'll have
                    // succeeded too.  Alternately, if we don't have any additional targets to check, then we want the
                    // overall result to reflect only the targets included in this result, which the OverallResult
                    // property already does -- so just default to true in that case as well.
                    _baseOverallResult = true;
                }
                else
                {
                    // If the existing result is a failure, then we need to determine whether the targets we are
                    // specifically interested in contributed to that failure or not.  If they did not, then this
                    // result should be sucessful even though the result it is based on failed.
                    //
                    // For the most part, this is taken care of for us because any dependent targets that fail also
                    // mark their parent targets (up to and including the entrypoint target) as failed.  However,
                    // there is one case in which this is not true: if the entrypoint target has AfterTargets that
                    // fail, then as far as the entrypoint target knows when it is executing, it has succeeded.  The
                    // failure doesn't come until after.  On the other hand, we don't want to actually include the
                    // AfterTarget results in the build result itself if the user hasn't asked for them.
                    //
                    // So in the case where there are AfterTargets, we will check them for failure so that we can
                    // make sure the overall success/failure result is correct, but not actually add their contents
                    // to the new result.
                    _baseOverallResult = true;

                    foreach (string additionalTarget in additionalTargetsToCheck)
                    {
                        if (existingResults.ResultsByTarget.TryGetValue(additionalTarget, out TargetResult targetResult))
                        {
                            if (targetResult.ResultCode == TargetResultCode.Failure && !targetResult.TargetFailureDoesntCauseBuildFailure)
                            {
                                _baseOverallResult = false;
                                break;
                            }
                        }
                    }
                }
            }
        }
示例#27
0
 internal BuildResult(MSB.Execution.BuildResult result, MSB.Execution.ProjectInstance instance)
 {
     this.Result   = result;
     this.Instance = instance;
 }
示例#28
0
        /// <summary>
        /// Completes this request.
        /// </summary>
        public void Complete(BuildResult result)
        {
            VerifyOneOfStates(new SchedulableRequestState[] { SchedulableRequestState.Ready, SchedulableRequestState.Executing, SchedulableRequestState.Unscheduled });
            ErrorUtilities.VerifyThrow(_state != SchedulableRequestState.Ready || result.CircularDependency, "Request can only be Completed from the Ready state if the result indicates a circular dependency occurred.");
            ErrorUtilities.VerifyThrow(_requestsWeAreBlockedBy.Count == 0, "We can't be complete if we are still blocked on requests.");

            // Any requests we were blocking we will no longer be blocking.
            List<SchedulableRequest> requestsToUnblock = new List<SchedulableRequest>(_requestsWeAreBlocking);
            foreach (SchedulableRequest requestWeAreBlocking in requestsToUnblock)
            {
                requestWeAreBlocking.UnblockWithResult(result);
            }

            ChangeToState(SchedulableRequestState.Completed);
        }
        private void DumpAnalyzerLists(BuildResult actualResult, string[] expected)
        {
            this.TestContext.WriteLine("");
            this.TestContext.WriteLine("Dumping analyzer list: expected");
            foreach (string analyzer in expected)
            {
                this.TestContext.WriteLine("\t{0}", analyzer);
            }
            this.TestContext.WriteLine("");

            this.TestContext.WriteLine("");
            this.TestContext.WriteLine("Dumping analyzer list: actual");
            foreach (ProjectItemInstance analyzer in actualResult.ProjectStateAfterBuild.GetItems(TargetProperties.AnalyzerItemType))
            {
                this.TestContext.WriteLine("\t{0}", analyzer.EvaluatedInclude);
            }
            this.TestContext.WriteLine("");
        }
示例#30
0
        /// <summary>
        /// Creates a build request entry from a build request.
        /// </summary>
        /// <param name="request">The originating build request.</param>
        /// <param name="requestConfiguration">The build request configuration.</param>
        internal BuildRequestEntry(BuildRequest request, BuildRequestConfiguration requestConfiguration)
        {
            ErrorUtilities.VerifyThrowArgumentNull(request, "request");
            ErrorUtilities.VerifyThrowArgumentNull(requestConfiguration, "requestConfiguration");
            ErrorUtilities.VerifyThrow(requestConfiguration.ConfigurationId == request.ConfigurationId, "Configuration id mismatch");

            _dataMonitor = new Object();
            _request = request;
            _requestConfiguration = requestConfiguration;
            _blockingGlobalRequestId = BuildRequest.InvalidGlobalRequestId;
            _completedResult = null;
            ChangeState(BuildRequestEntryState.Ready);
        }
示例#31
0
 /// <summary>
 /// Constructs a new build result with existing results, but associated with the specified request.
 /// </summary>
 /// <param name="request">The build request with which these results should be associated.</param>
 /// <param name="existingResults">The existing results, if any.</param>
 /// <param name="exception">The exception, if any</param>
 internal BuildResult(BuildRequest request, BuildResult existingResults, Exception exception)
     : this(request, existingResults, null, null, exception)
 {
 }
示例#32
0
        /// <summary>
        /// Marks this entry as complete and sets the final results.
        /// </summary>
        /// <param name="result">The result of the build.</param>
        public void Complete(BuildResult result)
        {
            lock (_dataMonitor)
            {
                ErrorUtilities.VerifyThrowArgumentNull(result, "result");
                ErrorUtilities.VerifyThrow(_completedResult == null, "Entry already Completed.");

                // If this request is determined to be a success, then all outstanding items must have been taken care of
                // and it must be in the correct state.  It can complete unsuccessfully for a variety of reasons in a variety 
                // of states.
                if (result.OverallResult == BuildResultCode.Success)
                {
                    ErrorUtilities.VerifyThrow(_state == BuildRequestEntryState.Active, "Entry must be active before it can be Completed successfully.  Config: {0} State: {1}", _requestConfiguration.ConfigurationId, _state);
                    ErrorUtilities.VerifyThrow(_unresolvedConfigurations == null, "Entry must not have any unresolved configurations.");
                    ErrorUtilities.VerifyThrow(_outstandingRequests == null, "Entry must have no outstanding requests.");
                    ErrorUtilities.VerifyThrow(_outstandingResults == null, "Results must be consumed before request may be completed.");
                }

                _completedResult = result;
                ChangeState(BuildRequestEntryState.Complete);
            }
        }
 public void AddResult(BuildResult result)
 {
     CurrentCache.AddResult(result);
 }
示例#34
0
        /// <summary>
        /// Indicates that there are results which can be used to unblock this request.  Updates the relationships between requests.
        /// </summary>
        public void UnblockWithResult(BuildResult result)
        {
            VerifyOneOfStates(new SchedulableRequestState[] { SchedulableRequestState.Blocked, SchedulableRequestState.Unscheduled });
            ErrorUtilities.VerifyThrowArgumentNull(result, "result");

            BlockingRequestKey key = new BlockingRequestKey(result);
            DisconnectRequestWeAreBlockedBy(key);
            _activeTargetsWhenBlocked = null;
        }
示例#35
0
        public static BuildResult Build(
            string solutionFile, string buildConfiguration = null,
            string buildPlatform = null, string buildTarget = "Build",
            string logVerbosity  = null, bool?inProcess     = null
            )
        {
            bool defaultInProcess = Debugger.IsAttached;

            if (!inProcess.GetValueOrDefault(defaultInProcess))
            {
                var argsDict = new Dictionary <string, object> {
                    { "solutionFile", solutionFile },
                    { "buildConfiguration", buildConfiguration },
                    { "buildPlatform", buildPlatform },
                    { "buildTarget", buildTarget },
                    { "logVerbosity", logVerbosity }
                };
                return(OutOfProcessBuild(argsDict));
            }

            string configString = String.Format("{0}|{1}", buildConfiguration ?? "<default>", buildPlatform ?? "<default>");

            if ((buildConfiguration ?? buildPlatform) != null)
            {
                Console.Error.WriteLine("// Running target '{2}' of '{0}' ({1}) ...", JSIL.Compiler.Program.ShortenPath(solutionFile), configString, buildTarget);
            }
            else
            {
                Console.Error.WriteLine("// Running target '{1}' of '{0}' ...", JSIL.Compiler.Program.ShortenPath(solutionFile), buildTarget);
            }

            var pc               = new ProjectCollection();
            var parms            = new BuildParameters(pc);
            var globalProperties = new Dictionary <string, string>();

            var             hostServices  = new HostServices();
            var             eventRecorder = new BuildEventRecorder();
            LoggerVerbosity _logVerbosity;

            if ((logVerbosity == null) || !Enum.TryParse(logVerbosity, out _logVerbosity))
            {
                _logVerbosity = LoggerVerbosity.Quiet;
            }

            parms.Loggers = new ILogger[] {
                new ConsoleLogger(_logVerbosity), eventRecorder
            };

            var manager = BuildManager.DefaultBuildManager;

            Console.Error.Write("// Generating MSBuild projects for solution '{0}'...", Path.GetFileName(solutionFile));
            // Begin a fake build so the manager has a logger available.
            manager.BeginBuild(parms);

            var projects = ParseSolutionFile(
                solutionFile, buildConfiguration, buildPlatform,
                globalProperties, manager
                );

            manager.EndBuild();
            Console.Error.WriteLine(" {0} project(s) generated.", projects.Length);

            if (File.ReadAllText(solutionFile).Contains("ProjectSection(ProjectDependencies)"))
            {
                Console.Error.WriteLine("// WARNING: Your solution file contains project dependencies. MSBuild ignores these, so your build may fail. If it does, try building it in Visual Studio first to resolve the dependencies.");
            }

            var allItemsBuilt = new List <BuiltItem>();
            var resultFiles   = new HashSet <string>();

            foreach (var project in projects)
            {
                // Save out the generated msbuild project for each solution, to aid debugging.
                try {
                    project.ToProjectRootElement().Save(project.FullPath, Encoding.UTF8);
                } catch (Exception exc) {
                    Console.Error.WriteLine("// Failed to save generated project '{0}': {1}", Path.GetFileName(project.FullPath), exc.Message);
                }
            }

            foreach (var project in projects)
            {
                Console.Error.WriteLine("// Building project '{0}'...", project.FullPath);

                var request = new BuildRequestData(
                    project, new string[] { buildTarget },
                    hostServices, BuildRequestDataFlags.None
                    );

                Microsoft.Build.Execution.BuildResult result = null;
                try {
                    result = manager.Build(parms, request);
                } catch (Exception exc) {
                    Console.Error.WriteLine("// Compilation failed: {0}", exc.Message);
                    continue;
                }

                allItemsBuilt.AddRange(ExtractChildProjectResults(manager));

                foreach (var kvp in result.ResultsByTarget)
                {
                    var targetResult = kvp.Value;

                    if ((targetResult.Exception != null) || (targetResult.ResultCode == TargetResultCode.Failure))
                    {
                        string errorMessage = "Unknown error";
                        if (targetResult.Exception != null)
                        {
                            errorMessage = targetResult.Exception.Message;
                        }
                        Console.Error.WriteLine("// Compilation failed for target '{0}': {1}", kvp.Key, errorMessage);
                    }
                }
            }

            // ResultsByTarget doesn't reliably produce all the output executables, so we must
            //  extract them by hand.
            foreach (var builtItem in allItemsBuilt)
            {
                if (builtItem.TargetName != "Build")
                {
                    continue;
                }

                if (!File.Exists(builtItem.OutputPath))
                {
                    Console.Error.WriteLine("// Ignoring nonexistent build output '" + Path.GetFileName(builtItem.OutputPath) + "'.");
                    continue;
                }

                var extension = Path.GetExtension(builtItem.OutputPath).ToLowerInvariant();

                switch (extension)
                {
                case ".exe":
                case ".dll":
                    resultFiles.Add(builtItem.OutputPath);
                    break;

                default:
                    Console.Error.WriteLine("// Ignoring build output '" + Path.GetFileName(builtItem.OutputPath) + "' due to unknown file type.");
                    break;
                }
            }

            return(new BuildResult(
                       Path.GetFullPath(solutionFile),
                       resultFiles.ToArray(),
                       eventRecorder.ProjectsById.Values.ToArray(),
                       eventRecorder.TargetFiles.ToArray(),
                       allItemsBuilt.ToArray()
                       ));
        }
示例#36
0
 /// <summary>
 /// Constructor over a result.
 /// </summary>
 public BlockingRequestKey(BuildResult result)
 {
     _globalRequestId = result.GlobalRequestId;
     _nodeRequestId = result.NodeRequestId;
 }
        /// <summary>
        /// Creates the target result dictionary and populates it with however many target results are
        /// available given the list of targets passed.
        /// </summary>
        private ConcurrentDictionary <string, TargetResult> CreateTargetResultDictionaryWithContents(BuildResult existingResults, string[] targetNames)
        {
            var resultsByTarget = CreateTargetResultDictionary(targetNames.Length);

            foreach (string target in targetNames)
            {
                TargetResult targetResult;
                if (existingResults.ResultsByTarget.TryGetValue(target, out targetResult))
                {
                    resultsByTarget[target] = targetResult;
                }
            }

            return(resultsByTarget);
        }