Example #1
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);
        }
        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);
            }
        }
Example #3
0
        /// <summary>
        /// Indicates to the TaskHost that it is no longer needed.
        /// Called by TaskBuilder when the task using the EngineProxy is done.
        /// </summary>
        internal void MarkAsInactive()
        {
            lock (_callbackMonitor)
            {
                VerifyActiveProxy();
                _activeProxy = false;

                // Since the task has a pointer to this class it may store it in a static field. Null out
                // internal data so the leak of this object doesn't lead to a major memory leak.
                _host         = null;
                _requestEntry = null;

                // Don't bother clearing the tiny task location
                _taskLoggingContext    = null;
                _targetBuilderCallback = null;

                // Clear out the sponsor (who is responsible for keeping the EngineProxy remoting lease alive until the task is done)
                // this will be null if the engine proxy was never sent across an AppDomain boundary.
                if (_sponsor != null)
                {
                    ILease lease = (ILease)RemotingServices.GetLifetimeService(this);

                    if (lease != null)
                    {
                        lease.Unregister(_sponsor);
                    }

                    _sponsor.Close();
                    _sponsor = null;
                }
            }
        }
Example #4
0
 public void TestConstructorNullTarget()
 {
     ProjectInstance project = CreateTestProject(true /* Returns enabled */);
     BuildRequestConfiguration config = new BuildRequestConfiguration(1, new BuildRequestData("foo", new Dictionary<string, string>(), "foo", new string[0], null), "2.0");
     BuildRequestEntry requestEntry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "foo" }), config);
     Lookup lookup = new Lookup(new ItemDictionary<ProjectItemInstance>(project.Items), new PropertyDictionary<ProjectPropertyInstance>(project.Properties), null);
     TargetEntry entry = new TargetEntry(requestEntry, this, null, lookup, null, _host, false);
 }
 public void TestConstructorBad()
 {
     Assert.Throws<ArgumentNullException>(() =>
     {
         BuildRequestEntry entry = new BuildRequestEntry(null, null);
     }
    );
 }
        public void TestConstructorGood()
        {
            BuildRequest request = CreateNewBuildRequest(1, new string[0] { });
            BuildRequestData data = new BuildRequestData("foo", new Dictionary<string, string>(), "foo", new string[0], null);
            BuildRequestConfiguration config = new BuildRequestConfiguration(1, data, "2.0");
            BuildRequestEntry entry = new BuildRequestEntry(request, config);

            Assert.AreEqual(entry.State, BuildRequestEntryState.Ready);
            Assert.AreEqual(entry.Request, request);
        }
Example #7
0
 public QAMockTargetBuilder()
 {
     _host = null;
     _testDataProvider = null;
     _testDefinition = null;
     _requestCallBack = null;
     _requestEntry = null;
     _projectLoggingContext = null;
     _buildDone = new AutoResetEvent(false);
 }
Example #8
0
        /// <summary>
        /// Builds the specified targets of an entry. The cancel event should only be set to true if we are planning
        /// on simulating execution time when a target is built
        /// </summary>
        public Task<BuildResult> BuildTargets(ProjectLoggingContext loggingContext, BuildRequestEntry entry, IRequestBuilderCallback callback, string[] targetNames, Lookup baseLookup, CancellationToken cancellationToken)
        {
            _requestEntry = entry;
            _projectLoggingContext = loggingContext;
            _requestCallBack = callback;
            _testDefinition = _testDataProvider[entry.Request.ConfigurationId];
            _cancellationToken = cancellationToken;
            BuildResult result = GenerateResults(targetNames);

            return Task<BuildResult>.FromResult(result);
        }
Example #9
0
 /// <summary>
 /// Constructor that takes in nothing.
 /// </summary>
 public QARequestBuilder()
 {
     _host = null;
     _configCache = null;
     _resultsCache = null;
     _builderThread = null;
     _requestedEntry = null;
     _cancelEvent = new AutoResetEvent(false);
     _continueEvent = new AutoResetEvent(false);
     _threadStarted = new ManualResetEvent(false);
     _currentProjectDefinition = null;
 }
            public void BuildRequest(NodeLoggingContext context, BuildRequestEntry entry)
            {
                Assert.Null(_builderThread); // "Received BuildRequest while one was in progress"

                _continueEvent = new AutoResetEvent(false);
                _cancelEvent = new AutoResetEvent(false);
                _entry = entry;
                entry.Continue();

                _builderThread = new Thread(BuilderThreadProc);
                _builderThread.Start();
            }
Example #11
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="host">The component host</param>
        /// <param name="requestEntry">The build request entry</param>
        /// <param name="taskLocation">The <see cref="ElementLocation"/> of the task.</param>
        /// <param name="targetBuilderCallback">An <see cref="ITargetBuilderCallback"/> to use to invoke targets and build projects.</param>
        public TaskHost(IBuildComponentHost host, BuildRequestEntry requestEntry, ElementLocation taskLocation, ITargetBuilderCallback targetBuilderCallback)
        {
            ErrorUtilities.VerifyThrowArgumentNull(host, "host");
            ErrorUtilities.VerifyThrowArgumentNull(requestEntry, "requestEntry");
            ErrorUtilities.VerifyThrowInternalNull(taskLocation, "taskLocation");

            _host                  = host;
            _requestEntry          = requestEntry;
            _taskLocation          = taskLocation;
            _targetBuilderCallback = targetBuilderCallback;
            _continueOnError       = false;
            _activeProxy           = true;
            _callbackMonitor       = new Object();
        }
        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);
        }
Example #13
0
        /// <summary>
        /// The constructor.
        /// </summary>
        /// <param name="requestEntry">The build request entry for the target.</param>
        /// <param name="targetBuilderCallback">The target builder callback.</param>
        /// <param name="targetSpecification">The specification for the target to build.</param>
        /// <param name="baseLookup">The lookup to use.</param>
        /// <param name="parentTarget">The parent of this entry, if any.</param>
        /// <param name="host">The Build Component Host to use.</param>
        /// <param name="stopProcessingOnCompletion">True if the target builder should stop processing the current target stack when this target is complete.</param>
        internal TargetEntry(BuildRequestEntry requestEntry, ITargetBuilderCallback targetBuilderCallback, TargetSpecification targetSpecification, Lookup baseLookup, TargetEntry parentTarget, IBuildComponentHost host, bool stopProcessingOnCompletion)
        {
            ErrorUtilities.VerifyThrowArgumentNull(requestEntry, "requestEntry");
            ErrorUtilities.VerifyThrowArgumentNull(targetBuilderCallback, "targetBuilderCallback");
            ErrorUtilities.VerifyThrowArgumentNull(targetSpecification, "targetName");
            ErrorUtilities.VerifyThrowArgumentNull(baseLookup, "lookup");
            ErrorUtilities.VerifyThrowArgumentNull(host, "host");

            _requestEntry          = requestEntry;
            _targetBuilderCallback = targetBuilderCallback;
            _targetSpecification   = targetSpecification;
            _parentTarget          = parentTarget;
            _expander   = new Expander <ProjectPropertyInstance, ProjectItemInstance>(baseLookup.ReadOnlyLookup, baseLookup.ReadOnlyLookup);
            _state      = TargetEntryState.Dependencies;
            _baseLookup = baseLookup;
            _host       = host;
            this.StopProcessingOnCompletion = stopProcessingOnCompletion;
        }
        public void TestMixedWaitingRequests()
        {
            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);

            entry.Continue();
            Assert.AreEqual(entry.State, BuildRequestEntryState.Active);

            BuildRequest waitingRequest1 = CreateNewBuildRequest(2, new string[1] { "bar" });
            entry.WaitForResult(waitingRequest1);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Waiting);

            BuildRequest waitingRequest2 = CreateNewBuildRequest(-1, new string[1] { "xor" });
            entry.WaitForResult(waitingRequest2);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Waiting);

            Assert.IsNull(entry.GetRequestsToIssueIfReady(), "Entry should not be ready to issue because there are unresolved configurations");

            entry.ResolveConfigurationRequest(-1, 3);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Waiting);

            BuildResult requiredResult1 = new BuildResult(waitingRequest1);
            requiredResult1.AddResultsForTarget("bar", TestUtilities.GetEmptySucceedingTargetResult());
            entry.ReportResult(requiredResult1);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Waiting);

            BuildResult requiredResult2 = new BuildResult(waitingRequest2);
            requiredResult2.AddResultsForTarget("xor", TestUtilities.GetEmptySucceedingTargetResult());
            entry.ReportResult(requiredResult2);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Ready);
        }
        /// <summary>
        /// Builds the specified targets.
        /// </summary>
        /// <param name="loggingContext">The logging context for the project.</param>
        /// <param name="entry">The BuildRequestEntry for which we are building targets.</param>
        /// <param name="callback">The callback to be used to handle new project build requests.</param>
        /// <param name="targetNames">The names of the targets to build.</param>
        /// <param name="baseLookup">The Lookup containing all current items and properties for this target.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use when building the targets.</param>
        /// <returns>The target's outputs and result codes</returns>
        public async Task <BuildResult> BuildTargets(ProjectLoggingContext loggingContext, BuildRequestEntry entry, IRequestBuilderCallback callback, string[] targetNames, Lookup baseLookup, CancellationToken cancellationToken)
        {
            ErrorUtilities.VerifyThrowArgumentNull(loggingContext, "projectLoggingContext");
            ErrorUtilities.VerifyThrowArgumentNull(entry, "entry");
            ErrorUtilities.VerifyThrowArgumentNull(callback, "requestBuilderCallback");
            ErrorUtilities.VerifyThrowArgumentNull(targetNames, "targetNames");
            ErrorUtilities.VerifyThrowArgumentNull(baseLookup, "baseLookup");
            ErrorUtilities.VerifyThrow(targetNames.Length > 0, "List of targets must be non-empty");
            ErrorUtilities.VerifyThrow(_componentHost != null, "InitializeComponent must be called before building targets.");

            _requestEntry           = entry;
            _requestBuilderCallback = callback;
            _projectLoggingContext  = loggingContext;
            _cancellationToken      = cancellationToken;

            // Clone the base lookup so that if we are re-entered by another request while this one in blocked, we don't have visibility to
            // their state, and they have no visibility into ours.
            _baseLookup = baseLookup.Clone();

            _targetsToBuild = new ConcurrentStack <TargetEntry>();

            // Get the actual target objects from the names
            BuildRequestConfiguration configuration = _requestEntry.RequestConfiguration;

            bool previousCacheableStatus = configuration.IsCacheable;

            configuration.IsCacheable = false;
            configuration.RetrieveFromCache();
            _projectInstance = configuration.Project;

            // Now get the current results cache entry.
            ResultsCache resultsCache        = (ResultsCache)_componentHost.GetComponent(BuildComponentType.ResultsCache);
            BuildResult  existingBuildResult = null;

            resultsCache.ResultsDictionary.TryGetValue(_requestEntry.Request.ConfigurationId, out existingBuildResult);

            _buildResult = new BuildResult(entry.Request, existingBuildResult, null);

            if (existingBuildResult == null)
            {
                // Add this result so that if our project gets re-entered we won't rebuild any targets we have already built.
                resultsCache.AddResult(_buildResult);
            }

            List <TargetSpecification> targets = new List <TargetSpecification>(targetNames.Length);

            foreach (string targetName in targetNames)
            {
                var targetExists = _projectInstance.Targets.ContainsKey(targetName);
                if (!targetExists && entry.Request.BuildRequestDataFlags.HasFlag(BuildRequestDataFlags.SkipNonexistentTargets))
                {
                    _projectLoggingContext.LogComment(Framework.MessageImportance.Low,
                                                      "TargetSkippedWhenSkipNonexistentTargets", targetName);

                    continue;
                }

                targets.Add(new TargetSpecification(targetName, targetExists ? _projectInstance.Targets[targetName].Location : _projectInstance.ProjectFileLocation));
            }

            // Push targets onto the stack.  This method will reverse their push order so that they
            // get built in the same order specified in the array.
            await PushTargets(targets, null, baseLookup, false, false, TargetBuiltReason.None);

            // Now process the targets
            ITaskBuilder taskBuilder = _componentHost.GetComponent(BuildComponentType.TaskBuilder) as ITaskBuilder;

            try
            {
                await ProcessTargetStack(taskBuilder);
            }
            finally
            {
                // If there are still targets left on the stack, they need to be removed from the 'active targets' list
                foreach (TargetEntry target in _targetsToBuild)
                {
                    configuration.ActivelyBuildingTargets.Remove(target.Name);
                }

                ((IBuildComponent)taskBuilder).ShutdownComponent();
            }

            if (_cancellationToken.IsCancellationRequested)
            {
                throw new BuildAbortedException();
            }

            // Gather up outputs for the requested targets and return those.  All of our information should be in the base lookup now.
            BuildResult resultsToReport = new BuildResult(_buildResult, targetNames);

            // Return after-build project state if requested.
            if (_requestEntry.Request.BuildRequestDataFlags.HasFlag(BuildRequestDataFlags.ProvideProjectStateAfterBuild))
            {
                resultsToReport.ProjectStateAfterBuild = _projectInstance;
            }

            configuration.IsCacheable = previousCacheableStatus;

            return(resultsToReport);
        }
Example #16
0
 /// <summary>
 /// Not Implemented
 /// </summary>
 public void BuildRequest(NodeLoggingContext nodeLoggingContext, BuildRequestEntry entry)
 {
     throw new NotImplementedException();
 }
Example #17
0
        public void TestComplexOrdering2()
        {
            string projectBody = @"
<Target Name='BuildDep'>
    <BuildDepTask/>
</Target>

<Target Name='BeforeDepDep'>
    <BeforeDepDepTask/>
</Target>

<Target Name='BeforeBeforeDep' BeforeTargets='BeforeDep'>
    <BeforeBeforeDepTask/>
</Target>

<Target Name='AfterBeforeBeforeDep' AfterTargets='BeforeBeforeDep'>
    <AfterBeforeBeforeDepTask/>
</Target>

<Target Name='BeforeDep' DependsOnTargets='BeforeDepDep'>
    <BeforeDepTask/>
</Target>

<Target Name='Before' DependsOnTargets='BeforeDep' BeforeTargets='Build'>
    <BeforeTask/>
</Target>

<Target Name='AfterBeforeDepDep'>
    <AfterBeforeDepDepTask/>
</Target>

<Target Name='AfterBeforeDep' DependsOnTargets='AfterBeforeDepDep'>
    <AfterBeforeDepTask/>
</Target>

<Target Name='AfterBefore' DependsOnTargets='AfterBeforeDep' AfterTargets='Before'>
    <AfterBeforeTask/>
</Target>

<Target Name='Build' DependsOnTargets='BuildDep'>
    <BuildTask/>
</Target>

";

            ProjectInstance project = CreateTestProject(projectBody);

            TargetBuilder builder = (TargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
            IConfigCache cache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
            BuildRequestEntry entry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "Build" }), cache[1]);

            BuildResult result = builder.BuildTargets(GetProjectLoggingContext(entry), entry, this, entry.Request.Targets.ToArray(), CreateStandardLookup(project), CancellationToken.None).Result;
            AssertTaskExecutionOrder(new string[] { "BuildDepTask", "BeforeDepDepTask", "BeforeBeforeDepTask", "AfterBeforeBeforeDepTask", "BeforeDepTask", "BeforeTask", "AfterBeforeDepDepTask", "AfterBeforeDepTask", "AfterBeforeTask", "BuildTask" });
        }
Example #18
0
 /// <summary>
 /// Not Implemented
 /// </summary>
 private void MockIRequestBuilderCallback_OnBuildRequestCompleted(BuildRequestEntry completedEntry)
 {
     throw new NotImplementedException();
 }
 public void TestConstructorBad()
 {
     BuildRequestEntry entry = new BuildRequestEntry(null, null);
 }
        public void TestResultsWithNoMatch1()
        {
            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);

            entry.Continue();
            Assert.AreEqual(entry.State, BuildRequestEntryState.Active);

            BuildRequest waitingRequest1 = CreateNewBuildRequest(2, new string[1] { "bar" });
            entry.WaitForResult(waitingRequest1);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Waiting);

            BuildRequest randomRequest = CreateNewBuildRequest(3, new string[0]);
            BuildResult requiredResult = new BuildResult(randomRequest);
            requiredResult.AddResultsForTarget("bar", TestUtilities.GetEmptySucceedingTargetResult());
            entry.ReportResult(requiredResult);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Waiting);
        }
Example #21
0
        public void TestBeforeTargetsEscaped()
        {
            string projectBody = @"
<Target Name='Build;Me' Outputs='$(Test)'>
    <BuildTask/>
</Target>

<Target Name='Before' BeforeTargets='Build%3bMe'>
    <BeforeTask/>
</Target>";

            ProjectInstance project = CreateTestProject(projectBody);

            TargetBuilder builder = (TargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
            IConfigCache cache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
            BuildRequestEntry entry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "Build;Me" }), cache[1]);

            BuildResult result = builder.BuildTargets(GetProjectLoggingContext(entry), entry, this, entry.Request.Targets.ToArray(), CreateStandardLookup(project), CancellationToken.None).Result;
            AssertTaskExecutionOrder(new string[] { "BeforeTask", "BuildTask" });
        }
Example #22
0
        public void TestLegacyCallTarget()
        {
            string projectBody = @"
<Target Name='Build'>
    <CallTarget Targets='Foo;Goo'/>
</Target>

<Target Name='Foo' DependsOnTargets='Foo2'>
    <FooTarget/>
</Target>

<Target Name='Goo'>
    <GooTarget/>
</Target>

<Target Name='Foo2'>
    <Foo2Target/>
</Target>
";

            ProjectInstance project = CreateTestProject(projectBody);

            TargetBuilder builder = (TargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
            IConfigCache cache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
            BuildRequestEntry entry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "Build" }), cache[1]);

            BuildResult result = builder.BuildTargets(GetProjectLoggingContext(entry), entry, this, entry.Request.Targets.ToArray(), CreateStandardLookup(project), CancellationToken.None).Result;
            AssertTaskExecutionOrder(new string[] { "CallTarget", "Foo2Target", "FooTarget", "GooTarget" });
        }
Example #23
0
 /// <summary>
 /// Not Implemented
 /// </summary>
 private void MockIRequestBuilderCallback_OnBuildRequestBlocked(BuildRequestEntry sourceEntry, int blockingGlobalRequestId, string blockingTarget)
 {
     throw new NotImplementedException();
 }
Example #24
0
        public void TestDependencyBuildWithSkip()
        {
            ProjectInstance project = CreateTestProject();

            // DepSkip depends on Skip (which skips) but should succeed itself.
            TargetBuilder builder = (TargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
            IConfigCache cache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
            BuildRequestEntry entry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "DepSkip" }), cache[1]);
            BuildResult result = builder.BuildTargets(GetProjectLoggingContext(entry), entry, this, entry.Request.Targets.ToArray(), CreateStandardLookup(project), CancellationToken.None).Result;
            Assert.True(result.HasResultsForTarget("DepSkip"));
            Assert.False(result.HasResultsForTarget("Skip"));
            Assert.Equal(TargetResultCode.Success, result["DepSkip"].ResultCode);

            IResultsCache resultsCache = (IResultsCache)_host.GetComponent(BuildComponentType.ResultsCache);
            Assert.True(resultsCache.GetResultForRequest(entry.Request).HasResultsForTarget("SkipCondition"));
            Assert.Equal(TargetResultCode.Skipped, resultsCache.GetResultForRequest(entry.Request)["SkipCondition"].ResultCode);
        }
Example #25
0
        public void TestCancelWithNoEntriesAfterBuild()
        {
            string projectBody = @"
<Target Name='Build'>
    <BuildTask/>
</Target>
";

            ProjectInstance project = CreateTestProject(projectBody);

            TargetBuilder builder = (TargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
            IConfigCache cache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
            BuildRequestEntry entry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "Build" }), cache[1]);
            using (CancellationTokenSource source = new CancellationTokenSource())
            {
                BuildResult result = builder.BuildTargets(GetProjectLoggingContext(entry), entry, this, entry.Request.Targets.ToArray(), CreateStandardLookup(project), source.Token).Result;
                AssertTaskExecutionOrder(new string[] { "BuildTask" });

                // This simply should not fail.
                source.Cancel();
            }
        }
Example #26
0
        public void TestDependencyBuild()
        {
            ProjectInstance project = CreateTestProject();

            // The Baz project depends on the Bar target.  Both should succeed.
            TargetBuilder builder = (TargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
            IConfigCache cache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);

            BuildRequestEntry entry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "Baz" }), cache[1]);
            BuildResult result = builder.BuildTargets(GetProjectLoggingContext(entry), entry, this, entry.Request.Targets.ToArray(), CreateStandardLookup(project), CancellationToken.None).Result;

            // The result returned from the builder includes only those for the specified targets.
            Assert.True(result.HasResultsForTarget("Baz"));
            Assert.False(result.HasResultsForTarget("Bar"));
            Assert.Equal(TargetResultCode.Success, result["Baz"].ResultCode);

            // The results cache should have ALL of the results.
            IResultsCache resultsCache = (IResultsCache)_host.GetComponent(BuildComponentType.ResultsCache);
            Assert.True(resultsCache.GetResultForRequest(entry.Request).HasResultsForTarget("Bar"));
            Assert.Equal(TargetResultCode.Success, resultsCache.GetResultForRequest(entry.Request)["Bar"].ResultCode);
        }
        public void TestNoReadyToWaiting()
        {
            BuildRequest request = CreateNewBuildRequest(1, new string[1] { "foo" });
            BuildRequestData data1 = new BuildRequestData("foo", new Dictionary<string, string>(), "foo", new string[0], null);
            BuildRequestConfiguration config = new BuildRequestConfiguration(1, data1, "2.0");
            BuildRequestEntry entry = new BuildRequestEntry(request, config);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Ready);

            BuildRequest waitingRequest1 = CreateNewBuildRequest(2, new string[1] { "bar" });
            entry.WaitForResult(waitingRequest1);
        }
Example #28
0
        public void TestAfterTargetsSingleWithErrorAndParent()
        {
            string projectBody = @"
<Target Name='After' AfterTargets='Build'>
    <AfterTask/>
</Target>

<Target Name='Build'>
    <BuildTask/>
    <OnError ExecuteTargets='ErrorTarget'/>
</Target>

<Target Name='ErrorTarget'>
    <Error/>
</Target>

<Target Name='ErrorTarget2'>
    <Error2/>
</Target>

<Target Name='PostBuild' DependsOnTargets='Build'>
    <OnError ExecuteTargets='ErrorTarget2'/>
</Target>
";

            MockTaskBuilder taskBuilder = (MockTaskBuilder)_host.GetComponent(BuildComponentType.TaskBuilder);
            taskBuilder.FailTaskNumber = 2; // Succeed on BuildTask, fail on AfterTask

            ProjectInstance project = CreateTestProject(projectBody);

            TargetBuilder builder = (TargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
            IConfigCache cache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
            BuildRequestEntry entry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "PostBuild" }), cache[1]);

            BuildResult result = builder.BuildTargets(GetProjectLoggingContext(entry), entry, this, entry.Request.Targets.ToArray(), CreateStandardLookup(project), CancellationToken.None).Result;
            AssertTaskExecutionOrder(new string[] { "BuildTask", "AfterTask", "Error2" });
        }
        public void TestNoReadyToComplete()
        {
            BuildRequest request = CreateNewBuildRequest(1, new string[1] { "foo" });
            BuildRequestData data1 = new BuildRequestData("foo", new Dictionary<string, string>(), "foo", new string[0], null);
            BuildRequestConfiguration config = new BuildRequestConfiguration(1, data1, "2.0");
            BuildRequestEntry entry = new BuildRequestEntry(request, config);
            Assert.AreEqual(entry.State, BuildRequestEntryState.Ready);

            BuildResult requiredResult = new BuildResult(request);
            requiredResult.AddResultsForTarget("foo", TestUtilities.GetEmptySucceedingTargetResult());
            entry.Complete(requiredResult);
        }
Example #30
0
        public void TestAfterTargetsWithOneReferringToTwo()
        {
            string projectBody = @"
<Target Name='Build'>
    <BuildTask/>
</Target>

<Target Name='Foo'>
    <FooTask/>
</Target>

<Target Name='After' AfterTargets='Build;Foo'>
    <AfterTask/>
</Target>
";

            ProjectInstance project = CreateTestProject(projectBody);

            TargetBuilder builder = (TargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
            IConfigCache cache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
            BuildRequestEntry entry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "Foo" }), cache[1]);

            BuildResult result = builder.BuildTargets(GetProjectLoggingContext(entry), entry, this, entry.Request.Targets.ToArray(), CreateStandardLookup(project), CancellationToken.None).Result;
            AssertTaskExecutionOrder(new string[] { "FooTask", "AfterTask" });
        }
Example #31
0
        /// <summary>
        /// Builds the specified targets.
        /// </summary>
        /// <param name="loggingContext">The logging context for the project.</param>
        /// <param name="entry">The BuildRequestEntry for which we are building targets.</param>
        /// <param name="callback">The callback to be used to handle new project build requests.</param>
        /// <param name="targetNames">The names of the targets to build.</param>
        /// <param name="baseLookup">The Lookup containing all current items and properties for this target.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use when building the targets.</param>
        /// <returns>The target's outputs and result codes</returns>
        public async Task <BuildResult> BuildTargets(ProjectLoggingContext loggingContext, BuildRequestEntry entry, IRequestBuilderCallback callback, string[] targetNames, Lookup baseLookup, CancellationToken cancellationToken)
        {
            ErrorUtilities.VerifyThrowArgumentNull(loggingContext, "projectLoggingContext");
            ErrorUtilities.VerifyThrowArgumentNull(entry, nameof(entry));
            ErrorUtilities.VerifyThrowArgumentNull(callback, "requestBuilderCallback");
            ErrorUtilities.VerifyThrowArgumentNull(targetNames, nameof(targetNames));
            ErrorUtilities.VerifyThrowArgumentNull(baseLookup, nameof(baseLookup));
            ErrorUtilities.VerifyThrow(targetNames.Length > 0, "List of targets must be non-empty");
            ErrorUtilities.VerifyThrow(_componentHost != null, "InitializeComponent must be called before building targets.");

            _requestEntry           = entry;
            _requestBuilderCallback = callback;
            _projectLoggingContext  = loggingContext;
            _cancellationToken      = cancellationToken;

            // Clone the base lookup so that if we are re-entered by another request while this one in blocked, we don't have visibility to
            // their state, and they have no visibility into ours.
            _baseLookup = baseLookup.Clone();

            _targetsToBuild = new ConcurrentStack <TargetEntry>();

            // Get the actual target objects from the names
            BuildRequestConfiguration configuration = _requestEntry.RequestConfiguration;

            bool previousCacheableStatus = configuration.IsCacheable;

            configuration.IsCacheable = false;
            configuration.RetrieveFromCache();
            _projectInstance = configuration.Project;

            // Now get the current results cache entry.
            IResultsCache resultsCache        = (IResultsCache)_componentHost.GetComponent(BuildComponentType.ResultsCache);
            BuildResult   existingBuildResult = resultsCache.GetResultsForConfiguration(_requestEntry.Request.ConfigurationId);

            _buildResult = new BuildResult(entry.Request, existingBuildResult, null);

            if (existingBuildResult == null)
            {
                // Add this result so that if our project gets re-entered we won't rebuild any targets we have already built.
                resultsCache.AddResult(_buildResult);
            }

            List <TargetSpecification> targets = new List <TargetSpecification>(targetNames.Length);

            foreach (string targetName in targetNames)
            {
                var targetExists = _projectInstance.Targets.TryGetValue(targetName, out ProjectTargetInstance targetInstance);
                if (!targetExists && entry.Request.BuildRequestDataFlags.HasFlag(BuildRequestDataFlags.SkipNonexistentTargets))
                {
                    _projectLoggingContext.LogComment(Framework.MessageImportance.Low,
                                                      "TargetSkippedWhenSkipNonexistentTargets", targetName);
                }
                else
                {
                    targets.Add(new TargetSpecification(targetName, targetExists ? targetInstance.Location : _projectInstance.ProjectFileLocation));
                }
            }

            // Push targets onto the stack.  This method will reverse their push order so that they
            // get built in the same order specified in the array.
            await PushTargets(targets, null, baseLookup, false, false, TargetBuiltReason.None);

            // Now process the targets
            ITaskBuilder taskBuilder = _componentHost.GetComponent(BuildComponentType.TaskBuilder) as ITaskBuilder;

            var staticGraph = new StaticGraph();

            staticGraph.ProjectPath = _projectInstance.FullPath;
            try
            {
                await ProcessTargetStack(taskBuilder, staticGraph.StaticTargets);
            }
            finally
            {
                // If there are still targets left on the stack, they need to be removed from the 'active targets' list
                foreach (TargetEntry target in _targetsToBuild)
                {
                    configuration.ActivelyBuildingTargets.Remove(target.Name);
                }

                ((IBuildComponent)taskBuilder).ShutdownComponent();
            }

            if (_cancellationToken.IsCancellationRequested)
            {
                throw new BuildAbortedException();
            }

            if (entry.IsStatic)
            {
                using (var stream = new FileStream(Environment.GetEnvironmentVariable("MSBUILDSTATIC_OUTPUT"), FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
                {
                    staticGraph.Files = SimulatedFileSystem.Instance.KnownFiles.ToList();
                    new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(StaticGraph)).WriteObject(stream, staticGraph);
                }
            }

            // Gather up outputs for the requested targets and return those.  All of our information should be in the base lookup now.
            ComputeAfterTargetFailures(targetNames);
            BuildResult resultsToReport = new BuildResult(_buildResult, targetNames);

            // Return after-build project state if requested.
            if (_requestEntry.Request.BuildRequestDataFlags.HasFlag(BuildRequestDataFlags.ProvideProjectStateAfterBuild))
            {
                resultsToReport.ProjectStateAfterBuild = _projectInstance;
            }

            if (_requestEntry.Request.RequestedProjectState != null)
            {
                resultsToReport.ProjectStateAfterBuild =
                    _projectInstance.FilteredCopy(_requestEntry.Request.RequestedProjectState);
            }

            configuration.IsCacheable = previousCacheableStatus;

            return(resultsToReport);
        }
Example #32
0
        public void TestSimpleBuild()
        {
            ProjectInstance project = CreateTestProject();

            // The Empty target has no inputs or outputs.
            TargetBuilder builder = (TargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
            IConfigCache cache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
            BuildRequestEntry entry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "Empty" }), cache[1]);

            BuildResult result = builder.BuildTargets(GetProjectLoggingContext(entry), entry, this, entry.Request.Targets.ToArray(), CreateStandardLookup(project), CancellationToken.None).Result;
            Assert.True(result.HasResultsForTarget("Empty"));
            Assert.Equal(TargetResultCode.Success, result["Empty"].ResultCode);
            Assert.Equal(0, result["Empty"].Items.Length);
        }
Example #33
0
 /// <summary>
 /// Creates a project logging context.
 /// </summary>
 /// <param name="entry">The entry on which to base the logging context.</param>
 /// <returns>The context</returns>
 private ProjectLoggingContext GetProjectLoggingContext(BuildRequestEntry entry)
 {
     return new ProjectLoggingContext(new NodeLoggingContext(_host, 1, false), entry, null);
 }
Example #34
0
 /// <summary>
 /// Not Implemented
 /// </summary>
 private void MockIRequestBuilderCallback_OnNewBuildRequests(BuildRequestEntry sourceEntry, FullyQualifiedBuildRequest[] requests)
 {
     throw new NotImplementedException();
 }
Example #35
0
        /// <summary>
        /// Runs all of the tasks for this target, batched as necessary.
        /// </summary>
        internal async Task ExecuteTarget(ITaskBuilder taskBuilder, BuildRequestEntry requestEntry, ProjectLoggingContext projectLoggingContext, CancellationToken cancellationToken)
        {
#if MSBUILDENABLEVSPROFILING
            try
            {
                string beginTargetBuild = String.Format(CultureInfo.CurrentCulture, "Build Target {0} in Project {1} - Start", this.Name, projectFullPath);
                DataCollection.CommentMarkProfile(8800, beginTargetBuild);
#endif

            try
            {
                VerifyState(_state, TargetEntryState.Execution);
                ErrorUtilities.VerifyThrow(!_isExecuting, "Target {0} is already executing", _target.Name);
                _cancellationToken = cancellationToken;
                _isExecuting       = true;

                // Generate the batching buckets.  Note that each bucket will get a lookup based on the baseLookup.  This lookup will be in its
                // own scope, which we will collapse back down into the baseLookup at the bottom of the function.
                List <ItemBucket> buckets = BatchingEngine.PrepareBatchingBuckets(GetBatchableParametersForTarget(), _baseLookup, _target.Location);

                WorkUnitResult       aggregateResult      = new WorkUnitResult();
                TargetLoggingContext targetLoggingContext = null;
                bool   targetSuccess   = false;
                int    numberOfBuckets = buckets.Count;
                string projectFullPath = requestEntry.RequestConfiguration.ProjectFullPath;

                string parentTargetName = null;
                if (ParentEntry != null && ParentEntry.Target != null)
                {
                    parentTargetName = ParentEntry.Target.Name;
                }

                for (int i = 0; i < numberOfBuckets; i++)
                {
                    ItemBucket bucket = buckets[i];

                    // If one of the buckets failed, stop building.
                    if (aggregateResult.ActionCode == WorkUnitActionCode.Stop)
                    {
                        break;
                    }

                    targetLoggingContext = projectLoggingContext.LogTargetBatchStarted(projectFullPath, _target, parentTargetName);
                    WorkUnitResult bucketResult = null;
                    targetSuccess = false;

                    Lookup.Scope entryForInference = null;
                    Lookup.Scope entryForExecution = null;

                    try
                    {
                        // This isn't really dependency analysis.  This is up-to-date checking.  Based on this we will be able to determine if we should
                        // run tasks in inference or execution mode (or both) or just skip them altogether.
                        ItemDictionary <ProjectItemInstance> changedTargetInputs;
                        ItemDictionary <ProjectItemInstance> upToDateTargetInputs;
                        Lookup lookupForInference;
                        Lookup lookupForExecution;

                        // UNDONE: (Refactor) Refactor TargetUpToDateChecker to take a logging context, not a logging service.
                        TargetUpToDateChecker    dependencyAnalyzer = new TargetUpToDateChecker(requestEntry.RequestConfiguration.Project, _target, targetLoggingContext.LoggingService, targetLoggingContext.BuildEventContext);
                        DependencyAnalysisResult dependencyResult   = dependencyAnalyzer.PerformDependencyAnalysis(bucket, out changedTargetInputs, out upToDateTargetInputs);

                        switch (dependencyResult)
                        {
                        // UNDONE: Need to enter/leave debugger scope properly for the <Target> element.
                        case DependencyAnalysisResult.FullBuild:
                        case DependencyAnalysisResult.IncrementalBuild:
                        case DependencyAnalysisResult.SkipUpToDate:
                            // Create the lookups used to hold the current set of properties and items
                            lookupForInference = bucket.Lookup;
                            lookupForExecution = bucket.Lookup.Clone();

                            // Push the lookup stack up one so that we are only modifying items and properties in that scope.
                            entryForInference = lookupForInference.EnterScope("ExecuteTarget() Inference");
                            entryForExecution = lookupForExecution.EnterScope("ExecuteTarget() Execution");

                            // if we're doing an incremental build, we need to effectively run the task twice -- once
                            // to infer the outputs for up-to-date input items, and once to actually execute the task;
                            // as a result we need separate sets of item and property collections to track changes
                            if (dependencyResult == DependencyAnalysisResult.IncrementalBuild)
                            {
                                // subset the relevant items to those that are up-to-date
                                foreach (string itemType in upToDateTargetInputs.ItemTypes)
                                {
                                    lookupForInference.PopulateWithItems(itemType, upToDateTargetInputs[itemType]);
                                }

                                // subset the relevant items to those that have changed
                                foreach (string itemType in changedTargetInputs.ItemTypes)
                                {
                                    lookupForExecution.PopulateWithItems(itemType, changedTargetInputs[itemType]);
                                }
                            }

                            // We either have some work to do or at least we need to infer outputs from inputs.
                            bucketResult = await ProcessBucket(taskBuilder, targetLoggingContext, GetTaskExecutionMode(dependencyResult), lookupForInference, lookupForExecution);

                            // Now aggregate the result with the existing known results.  There are four rules, assuming the target was not
                            // skipped due to being up-to-date:
                            // 1. If this bucket failed or was cancelled, the aggregate result is failure.
                            // 2. If this bucket Succeeded and we have not previously failed, the aggregate result is a success.
                            // 3. Otherwise, the bucket was skipped, which has no effect on the aggregate result.
                            // 4. If the bucket's action code says to stop, then we stop, regardless of the success or failure state.
                            if (dependencyResult != DependencyAnalysisResult.SkipUpToDate)
                            {
                                aggregateResult = aggregateResult.AggregateResult(bucketResult);
                            }
                            else
                            {
                                if (aggregateResult.ResultCode == WorkUnitResultCode.Skipped)
                                {
                                    aggregateResult = aggregateResult.AggregateResult(new WorkUnitResult(WorkUnitResultCode.Success, WorkUnitActionCode.Continue, null));
                                }
                            }

                            // Pop the lookup scopes, causing them to collapse their values back down into the
                            // bucket's lookup.
                            // NOTE: this order is important because when we infer outputs, we are trying
                            // to produce the same results as would be produced from a full build; as such
                            // if we're doing both the infer and execute steps, we want the outputs from
                            // the execute step to override the outputs of the infer step -- this models
                            // the full build scenario more correctly than if the steps were reversed
                            entryForInference.LeaveScope();
                            entryForInference = null;
                            entryForExecution.LeaveScope();
                            entryForExecution = null;
                            targetSuccess     = (bucketResult != null) && (bucketResult.ResultCode == WorkUnitResultCode.Success);
                            break;

                        case DependencyAnalysisResult.SkipNoInputs:
                        case DependencyAnalysisResult.SkipNoOutputs:
                            // We have either no inputs or no outputs, so there is nothing to do.
                            targetSuccess = true;
                            break;
                        }
                    }
                    catch (InvalidProjectFileException e)
                    {
                        // Make sure the Invalid Project error gets logged *before* TargetFinished.  Otherwise,
                        // the log is confusing.
                        targetLoggingContext.LogInvalidProjectFileError(e);

                        if (null != entryForInference)
                        {
                            entryForInference.LeaveScope();
                        }

                        if (null != entryForExecution)
                        {
                            entryForExecution.LeaveScope();
                        }

                        aggregateResult = aggregateResult.AggregateResult(new WorkUnitResult(WorkUnitResultCode.Failed, WorkUnitActionCode.Stop, null));
                    }
                    finally
                    {
                        // Don't log the last target finished event until we can process the target outputs as we want to attach them to the
                        // last target batch.
                        if (targetLoggingContext != null && i < numberOfBuckets - 1)
                        {
                            targetLoggingContext.LogTargetBatchFinished(projectFullPath, targetSuccess, null);
                            targetLoggingContext = null;
                        }
                    }
                }

                // Produce the final results.
                List <TaskItem> targetOutputItems = new List <TaskItem>();

                try
                {
                    // If any legacy CallTarget operations took place, integrate them back in to the main lookup now.
                    LeaveLegacyCallTargetScopes();

                    // Publish the items for each bucket back into the baseLookup.  Note that EnterScope() was actually called on each
                    // bucket inside of the ItemBucket constructor, which is why you don't see it anywhere around here.
                    foreach (ItemBucket bucket in buckets)
                    {
                        bucket.LeaveScope();
                    }

                    string          targetReturns         = _target.Returns;
                    ElementLocation targetReturnsLocation = _target.ReturnsLocation;

                    // If there are no targets in the project file that use the "Returns" attribute, that means that we
                    // revert to the legacy behavior in the case where Returns is not specified (null, rather
                    // than the empty string, which indicates no returns).  Legacy behavior is for all
                    // of the target's Outputs to be returned.
                    // On the other hand, if there is at least one target in the file that uses the Returns attribute,
                    // then all targets in the file are run according to the new behaviour (return nothing unless otherwise
                    // specified by the Returns attribute).
                    if (targetReturns == null)
                    {
                        if (!_target.ParentProjectSupportsReturnsAttribute)
                        {
                            targetReturns         = _target.Outputs;
                            targetReturnsLocation = _target.OutputsLocation;
                        }
                    }

                    if (!String.IsNullOrEmpty(targetReturns))
                    {
                        // Determine if we should keep duplicates.
                        bool keepDupes = ConditionEvaluator.EvaluateCondition
                                         (
                            _target.KeepDuplicateOutputs,
                            ParserOptions.AllowPropertiesAndItemLists,
                            _expander,
                            ExpanderOptions.ExpandPropertiesAndItems,
                            requestEntry.ProjectRootDirectory,
                            _target.KeepDuplicateOutputsLocation,
                            projectLoggingContext.LoggingService,
                            projectLoggingContext.BuildEventContext
                                         );

                        // NOTE: we need to gather the outputs in batches, because the output specification may reference item metadata
                        // Also, we are using the baseLookup, which has possibly had changes made to it since the project started.  Because of this, the
                        // set of outputs calculated here may differ from those which would have been calculated at the beginning of the target.  It is
                        // assumed the user intended this.
                        List <ItemBucket> batchingBuckets = BatchingEngine.PrepareBatchingBuckets(GetBatchableParametersForTarget(), _baseLookup, _target.Location);

                        if (keepDupes)
                        {
                            foreach (ItemBucket bucket in batchingBuckets)
                            {
                                targetOutputItems.AddRange(bucket.Expander.ExpandIntoTaskItemsLeaveEscaped(targetReturns, ExpanderOptions.ExpandAll, targetReturnsLocation));
                            }
                        }
                        else
                        {
                            HashSet <TaskItem> addedItems = new HashSet <TaskItem>();
                            foreach (ItemBucket bucket in batchingBuckets)
                            {
                                IList <TaskItem> itemsToAdd = bucket.Expander.ExpandIntoTaskItemsLeaveEscaped(targetReturns, ExpanderOptions.ExpandAll, targetReturnsLocation);

                                foreach (TaskItem item in itemsToAdd)
                                {
                                    if (!addedItems.Contains(item))
                                    {
                                        targetOutputItems.Add(item);
                                        addedItems.Add(item);
                                    }
                                }
                            }
                        }
                    }
                }
                finally
                {
                    if (targetLoggingContext != null)
                    {
                        // log the last target finished since we now have the target outputs.
                        targetLoggingContext.LogTargetBatchFinished(projectFullPath, targetSuccess, targetOutputItems != null && targetOutputItems.Count > 0 ? targetOutputItems : null);
                    }
                }

                _targetResult = new TargetResult(targetOutputItems.ToArray(), aggregateResult);

                if (aggregateResult.ResultCode == WorkUnitResultCode.Failed && aggregateResult.ActionCode == WorkUnitActionCode.Stop)
                {
                    _state = TargetEntryState.ErrorExecution;
                }
                else
                {
                    _state = TargetEntryState.Completed;
                }
            }
            finally
            {
                _isExecuting = false;
            }
#if MSBUILDENABLEVSPROFILING
        }

        finally
        {
            string endTargetBuild = String.Format(CultureInfo.CurrentCulture, "Build Target {0} in Project {1} - End", this.Name, projectFullPath);
            DataCollection.CommentMarkProfile(8801, endTargetBuild);
        }
#endif
        }
Example #36
0
        public void TestDependencyBuildWithError()
        {
            ProjectInstance project = CreateTestProject();

            // The DepError target builds Foo (which succeeds), Skip (which skips) and Error (which fails), and Baz2
            // Baz2 should not run since it came after Error.
            // Error tries to build Foo again as an error (which is already built) and Bar, which produces outputs.
            // DepError builds Baz as an error, which produces outputs
            TargetBuilder builder = (TargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
            MockTaskBuilder taskBuilder = (MockTaskBuilder)_host.GetComponent(BuildComponentType.TaskBuilder);
            taskBuilder.FailTaskNumber = 3; // Succeed on Foo's one task, and Error's first task, and fail the second.

            IConfigCache cache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
            BuildRequestEntry entry = new BuildRequestEntry(CreateNewBuildRequest(1, new string[] { "DepError" }), cache[1]);
            BuildResult result = builder.BuildTargets(GetProjectLoggingContext(entry), entry, this, entry.Request.Targets.ToArray(), CreateStandardLookup(project), CancellationToken.None).Result;
            Assert.True(result.HasResultsForTarget("DepError"));
            Assert.False(result.HasResultsForTarget("Foo"));
            Assert.False(result.HasResultsForTarget("Skip"));
            Assert.False(result.HasResultsForTarget("Error"));
            Assert.False(result.HasResultsForTarget("Baz2"));
            Assert.False(result.HasResultsForTarget("Bar"));
            Assert.False(result.HasResultsForTarget("Baz"));

            IResultsCache resultsCache = (IResultsCache)_host.GetComponent(BuildComponentType.ResultsCache);

            Assert.True(resultsCache.GetResultForRequest(entry.Request).HasResultsForTarget("Foo"));
            Assert.True(resultsCache.GetResultForRequest(entry.Request).HasResultsForTarget("Skip"));
            Assert.True(resultsCache.GetResultForRequest(entry.Request).HasResultsForTarget("Error"));
            Assert.False(resultsCache.GetResultForRequest(entry.Request).HasResultsForTarget("Baz2"));
            Assert.True(resultsCache.GetResultForRequest(entry.Request).HasResultsForTarget("Bar"));
            Assert.True(resultsCache.GetResultForRequest(entry.Request).HasResultsForTarget("Baz"));
            Assert.Equal(TargetResultCode.Failure, resultsCache.GetResultForRequest(entry.Request)["DepError"].ResultCode);
            Assert.Equal(TargetResultCode.Success, resultsCache.GetResultForRequest(entry.Request)["Foo"].ResultCode);
            Assert.Equal(TargetResultCode.Success, resultsCache.GetResultForRequest(entry.Request)["Skip"].ResultCode);
            Assert.Equal(TargetResultCode.Failure, resultsCache.GetResultForRequest(entry.Request)["Error"].ResultCode);
            Assert.Equal(TargetResultCode.Success, resultsCache.GetResultForRequest(entry.Request)["Bar"].ResultCode);
            Assert.Equal(TargetResultCode.Success, resultsCache.GetResultForRequest(entry.Request)["Baz"].ResultCode);
        }