示例#1
0
 public void TearDownAttribute()
 {
     engine.Shutdown();
     engineProxy = null;
     engineProxy2 = null;
     engine = null;
 }
示例#2
0
        public void SetUp()
        {
            // Whole bunch of setup code.
            XmlElement taskNode = new XmlDocument().CreateElement("MockTask");
            LoadedType taskClass = new LoadedType(typeof(MockTask), new AssemblyLoadInfo(typeof(MockTask).Assembly.FullName, null));
            engine = new Engine(@"c:\");
            Project project = new Project(engine);
            EngineCallback engineCallback = new EngineCallback(engine);
            taskExecutionModule = new MockTaskExecutionModule(engineCallback);
            int handleId = engineCallback.CreateTaskContext(project, null, null, taskNode, EngineCallback.inProcNode, new BuildEventContext(BuildEventContext.InvalidNodeId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId));
            TaskEngine taskEngine = new TaskEngine
                                (
                                    taskNode,
                                    null, /* host object */
                                    "In Memory",
                                    project.FullFileName,
                                    engine.LoggingServices,
                                    handleId,
                                    taskExecutionModule,
                                    null
                                );
            taskEngine.TaskClass = taskClass;

            engineProxy = new EngineProxy(taskExecutionModule, handleId, project.FullFileName, project.FullFileName, engine.LoggingServices, null);
            taskExecutionModule2 = new MockTaskExecutionModule(engineCallback, TaskExecutionModule.TaskExecutionModuleMode.MultiProcFullNodeMode);
            engineProxy2 = new EngineProxy(taskExecutionModule2, handleId, project.FullFileName, project.FullFileName, engine.LoggingServices, null);

        }
示例#3
0
        /// <summary>
        /// Creates an instance of a MockTask, and returns the objects necessary to exercise
        /// taskEngine.InitializeTask
        /// </summary>
        /// <param name="taskNode"></param>
        /// <param name="taskEngine"></param>
        /// <param name="mockTask"></param>
        /// <param name="itemBucket"></param>
        /// <owner>RGoel</owner>
        private void InstantiateMockTaskHelper
            (
            XmlElement taskNode,
            out TaskEngine taskEngine,
            out MockTask mockTask,
            out ItemBucket itemBucket,
            out EngineProxy engineProxy,
            string condition
            )
        {
            LoadedType taskClass = new LoadedType(typeof(MockTask), new AssemblyLoadInfo(typeof(MockTask).Assembly.FullName, null));
            Engine engine = new Engine(@"c:\");
            Project project = new Project(engine);
            EngineCallback engineCallback = new EngineCallback(engine);
            TaskExecutionModule taskExecutionModule = new TaskExecutionModule(engineCallback, 
                                        TaskExecutionModule.TaskExecutionModuleMode.SingleProcMode, false);
            ProjectBuildState buildContext = new ProjectBuildState(null, null, new BuildEventContext(0, 1, 1, 1));
            int nodeProxyID = engineCallback.CreateTaskContext(project, null, buildContext, taskNode, EngineCallback.inProcNode, new BuildEventContext(BuildEventContext.InvalidNodeId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId));
            taskEngine = new TaskEngine
                                (
                                    taskNode,
                                    null, /* host object */
                                    "In Memory",
                                    project.FullFileName,
                                    engine.LoggingServices,
                                    nodeProxyID,
                                    taskExecutionModule, 
                                    new BuildEventContext(0, 1, 1, 1)
                                );
            taskEngine.TaskClass = taskClass;
            engineProxy = new EngineProxy(taskExecutionModule, nodeProxyID, project.FullFileName, project.FullFileName, engine.LoggingServices, null);
            mockTask = new MockTask(new EngineProxy(taskExecutionModule, nodeProxyID, project.FullFileName, project.FullFileName, engine.LoggingServices, null));

            // The code below creates an item table that is equivalent to the following MSBuild syntax:
            //
            //      <ItemGroup>
            //          <ItemListContainingOneItem Include="a.cs">
            //              <Culture>fr-fr</Culture>
            //          </ItemListContainingOneItem>
            //
            //          <ItemListContainingTwoItems Include="b.cs">
            //              <HintPath>c:\foo</HintPath>
            //          </ItemListContainingTwoItems>
            //          <ItemListContainingTwoItems Include="c.cs">
            //              <HintPath>c:\bar</HintPath>
            //          </ItemListContainingTwoItems>
            //      </ItemGroup>
            //
            Hashtable itemsByName = new Hashtable(StringComparer.OrdinalIgnoreCase);

            BuildItemGroup itemListContainingOneItem = new BuildItemGroup();
            BuildItem a = itemListContainingOneItem.AddNewItem("ItemListContainingOneItem", "a.cs");
            a.SetMetadata("Culture", "fr-fr");
            itemsByName["ItemListContainingOneItem"] = itemListContainingOneItem;

            BuildItemGroup itemListContainingTwoItems = new BuildItemGroup();
            BuildItem b = itemListContainingTwoItems.AddNewItem("ItemListContainingTwoItems", "b.cs");
            b.SetMetadata("HintPath", "c:\\foo");
            BuildItem c = itemListContainingTwoItems.AddNewItem("ItemListContainingTwoItems", "c.cs");
            c.SetMetadata("HintPath", "c:\\bar");
            itemsByName["ItemListContainingTwoItems"] = itemListContainingTwoItems;

            itemBucket = new ItemBucket(new string[0], new Dictionary<string, string>(), LookupHelpers.CreateLookup(itemsByName), 0);
        }
示例#4
0
 /*********************************************************************************
  * 
  *                                     Helpers
  * 
  *********************************************************************************/
 private void InstantiateMockTaskHelper
     (
     XmlElement taskNode,
     out TaskEngine taskEngine,
     out MockTask mockTask,
     out ItemBucket itemBucket,
     out EngineProxy engineProxy
     )
 {
     InstantiateMockTaskHelper(taskNode, out taskEngine, out mockTask, out itemBucket, out engineProxy, null);
 }
示例#5
0
        /// <summary>
        /// Execute a task object for a given bucket.
        /// </summary>
        /// <param name="engineProxy"></param>
        /// <param name="bucket"></param>
        /// <param name="howToExecuteTask"></param>
        /// <param name="task"></param>
        /// <param name="taskResult">Whether the task returned true from Execute</param>
        /// <returns>true if task executed successfully (possibly failed but continueOnError=true)</returns>
        private bool ExecuteInstantiatedTask(EngineProxy engineProxy, ItemBucket bucket, TaskExecutionMode howToExecuteTask, ITask task, out bool taskResult)
        {
            UpdateContinueOnError(bucket, engineProxy);

            taskResult = false;
            bool taskExecutedSuccessfully = true;

            if (!InitializeTask(task, bucket, engineProxy))
            {
                // The task cannot be initialized.
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, taskNode, "TaskParametersError", TaskName, String.Empty);
            }
            else
            {
                bool taskReturned = false;

                try
                {
                    taskResult = task.Execute();
                    taskReturned = true;
                }
                // if a logger has failed, abort immediately
                catch (LoggerException)
                {
                    // Polite logger failure
                    throw;
                }
                catch (InternalLoggerException)
                {
                    // Logger threw arbitrary exception
                    throw;
                }
                // handle any exception thrown by the task during execution
                // NOTE: We catch ALL exceptions here, to attempt to completely isolate the Engine
                // from failures in the task. Probably we should try to avoid catching truly fatal exceptions,
                // e.g., StackOverflowException
                catch (Exception e)
                {
                    if (continueOnError)
                    {
                        loggingServices.LogTaskWarningFromException(buildEventContext, e,
                            // Don't try and log the line/column number for this error if
                            // ContinueOnError=true, because it's too expensive to do so, 
                            // and this error may be fairly common and expected.
                            new BuildEventFileInfo(projectFileOfTaskNode), TaskName);

                        // Log a message explaining why we converted the previous error into a warning.
                        loggingServices.LogComment(buildEventContext, MessageImportance.Normal, "ErrorConvertedIntoWarning");
                    }
                    else
                    {
                        loggingServices.LogFatalTaskError(buildEventContext, e,
                            CreateBuildEventFileInfoForTask(),
                            TaskName);
                    }
                }

                // If the task returned attempt to gather its outputs.  If gathering outputs fails set the taskResults
                // to false
                if (taskReturned)
                {
                    taskResult = GatherTaskOutputs(howToExecuteTask, task, bucket) && taskResult;
                }

                // If the taskResults are false look at ContinueOnError.  If ContinueOnError=false (default)
                // mark the taskExecutedSuccessfully=false.  Otherwise let the task succeed but log a normal
                // pri message that says this task is continuing because ContinueOnError=true
                if (!taskResult)
                {
                    if (!continueOnError)
                    {
                        taskExecutedSuccessfully = false;
                    }
                    else
                    {
                        loggingServices.LogComment(buildEventContext, MessageImportance.Normal,
                            "TaskContinuedDueToContinueOnError",
                             "ContinueOnError", TaskName, "true");
                    }
                }
            }

            return taskExecutedSuccessfully;
        }
示例#6
0
        /// <summary>
        /// Given an instantiated task, this method initializes it, and sets all the task parameters (which are defined as
        /// properties of the task class).
        /// </summary>
        /// <remarks>
        /// This method is internal for unit-testing purposes only.
        /// </remarks>
        /// <returns>true, if successful</returns>
        internal bool InitializeTask(ITask task, ItemBucket bucket, EngineProxy engineProxy)
        {
            try
            {
                task.BuildEngine = engineProxy;
                task.HostObject = hostObject;
            }
            // if a logger has failed, abort immediately
            catch (LoggerException)
            {
                // Polite logger failure
                throw;
            }
            catch (InternalLoggerException)
            {
                // Logger threw arbitrary exception
                throw;
            }
            // handle any exception thrown by the task during initialization
            catch (Exception e)
            {
                // NOTE: We catch ALL exceptions here, to attempt to completely isolate the Engine
                // from failures in the task. Probably we should try to avoid catching truly fatal exceptions,
                // e.g., StackOverflowException

                loggingServices.LogFatalTaskError(buildEventContext,
                     e,
                    // Display the task's exception stack.
                    // Log the task line number, whatever the value of ContinueOnError;
                    // because InitializeTask failure will be a hard error anyway.
                     CreateBuildEventFileInfoForTask(),
                     TaskName);

                return false;
            }

            bool taskInitialized = InitializeTaskParameters(task, bucket);

            return taskInitialized;
        }
示例#7
0
        /// <summary>
        /// Recomputes the task's "ContinueOnError" setting.
        /// </summary>
        /// <param name="bucket"></param>
        /// <param name="engineProxy"></param>
        private void UpdateContinueOnError(ItemBucket bucket, EngineProxy engineProxy)
        {
            XmlAttribute continueOnErrorAttribute = taskNode.Attributes[XMakeAttributes.continueOnError];

            try
            {
                continueOnError =
                (
                    // if attribute doesn't exist, default to "false"
                        (continueOnErrorAttribute != null)
                    &&
                    // otherwise, convert its value to a boolean
                        ConversionUtilities.ConvertStringToBool
                        (
                    // expand embedded item vectors after expanding properties and item metadata
                            bucket.Expander.ExpandAllIntoString(continueOnErrorAttribute)
                        )
                );
            }
            // handle errors in string-->bool conversion
            catch (ArgumentException e)
            {
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, continueOnErrorAttribute, "InvalidContinueOnErrorAttribute", TaskName, e.Message);
            }

            // We need to access an internal method of the EngineProxy in order to update the value
            // of continueOnError that will be returned to the task when the task queries IBuildEngine for it
            engineProxy.UpdateContinueOnError(continueOnError);
        }
示例#8
0
        /// <summary>
        /// Execute a single bucket
        /// </summary>
        /// <returns>true if execution succeeded</returns>
        private bool ExecuteBucket(EngineProxy engineProxy, ItemBucket bucket, int bucketNumber, TaskExecutionMode howToExecuteTask)
        {
            if (
                    (this.conditionAttribute != null)
                    &&
                    !Utilities.EvaluateCondition(this.conditionAttribute.Value, this.conditionAttribute,
                        bucket.Expander, null, ParserOptions.AllowAll, loggingServices, buildEventContext)
                )
            {
                // Condition is false
                if (howToExecuteTask == TaskExecutionMode.ExecuteTaskAndGatherOutputs)
                {
                    if (!loggingServices.OnlyLogCriticalEvents)
                    {
                        // Expand the expression for the Log.
                        string expanded = bucket.Expander.ExpandAllIntoString(this.conditionAttribute);
                        // Whilst we are within the processing of the task, we haven't actually started executing it, so
                        // our skip task message needs to be in the context of the target. However any errors should be reported
                        // at the point where the task appears in the project.
                        BuildEventContext skipTaskContext = new BuildEventContext(buildEventContext.NodeId, buildEventContext.TargetId, buildEventContext.ProjectContextId, BuildEventContext.InvalidTaskId);
                        loggingServices.LogComment(skipTaskContext,
                                        "TaskSkippedFalseCondition",
                                         TaskName, this.conditionAttribute.Value, expanded);
                    }
                }

                return true;
            }

            bool taskExecutedSuccessfully = true;

            // Condition is true
            if (howToExecuteTask == TaskExecutionMode.ExecuteTaskAndGatherOutputs)
            {
                // Now that we know we will need to execute the task,
                // Ensure the TaskEngine is initialized with the task class
                // This does the work of task discovery, if it 
                // hasn't already been done.
                bool taskClassWasFound = FindTask();

                if (!taskClassWasFound)
                {
                    // Task wasn't discovered, we cannot continue
                    return false;
                }

                // Now instantiate, initialize, and execute the task
                ITask task;

                // If this is the first bucket use the task context originally given to it, for the remaining buckets get a unique id for them
                if (bucketNumber != 0)
                {
		    // Ask the parent engine the next Id which should be used for the taskId.
                    buildEventContext = new BuildEventContext(buildEventContext.NodeId, buildEventContext.TargetId, buildEventContext.ProjectContextId, parentModule.GetNextTaskId());

		    // For each batch the engineProxy needs to have the correct buildEventContext as all messages comming from a task will have the buildEventContext of the EngineProxy.
                    engineProxy.BuildEventContext = buildEventContext;
                }

                loggingServices.LogTaskStarted(buildEventContext, TaskName, parentProjectFullFileName, projectFileOfTaskNode);

                AppDomain taskAppDomain = PrepareAppDomain();

                bool taskResult = false;

                try
                {
                    task = InstantiateTask(taskAppDomain);

                    // If task cannot be instantiated, we consider its declaration/usage to be invalid.
                    ProjectErrorUtilities.VerifyThrowInvalidProject(task != null, taskNode, "TaskDeclarationOrUsageError", TaskName);
                    taskExecutedSuccessfully = ExecuteInstantiatedTask(engineProxy, bucket, howToExecuteTask, task, out taskResult);
                    if (lookupHash != null)
                    {
                        List<string> overrideMessages = bucket.Lookup.GetPropertyOverrideMessages(lookupHash);
                        if (overrideMessages != null)
                        {
                            foreach (string s in overrideMessages)
                            {
                                loggingServices.LogCommentFromText(buildEventContext, MessageImportance.Low, s);
                            }
                        }
                    }
                }
                catch (InvalidProjectFileException e)
                {
                    // Make sure the Invalid Project error gets logged *before* TaskFinished.  Otherwise,
                    // the log is confusing.
                    loggingServices.LogInvalidProjectFileError(buildEventContext, e);
                    throw;
                }
                finally
                {
                    // Flag the completion of the task.
                    loggingServices.LogTaskFinished(
                        buildEventContext,
                        TaskName,
                        parentProjectFullFileName,
                        projectFileOfTaskNode,
                        taskResult);

                    task = null;

                    if (taskAppDomain != null)
                    {
                        AppDomain.Unload(taskAppDomain);
                        taskAppDomain = null;
                    }
                }
            }
            else
            {
                Debug.Assert(howToExecuteTask == TaskExecutionMode.InferOutputsOnly);

                ErrorUtilities.VerifyThrow(GatherTaskOutputs(howToExecuteTask, null, bucket),
                    "The method GatherTaskOutputs() should never fail when inferring task outputs.");
                if (lookupHash != null)
                {
                    List<string> overrideMessages = bucket.Lookup.GetPropertyOverrideMessages(lookupHash);
                    if (overrideMessages != null)
                    {
                        foreach (string s in overrideMessages)
                        {
                            loggingServices.LogCommentFromText(buildEventContext, MessageImportance.Low, s);
                        }
                    }
                }
            }

            return taskExecutedSuccessfully;
        }
示例#9
0
        /// <summary>
        /// Called to execute a task within a target. This method instantiates the task, sets its parameters, and executes it. 
        /// </summary>
        /// <returns>true, if successful</returns>
        internal bool ExecuteTask(TaskExecutionMode howToExecuteTask, Lookup lookup)
        {
            ErrorUtilities.VerifyThrow(lookup != null, "Need to specify items available to task.");

            bool taskExecutedSuccessfully = false;
            EngineProxy engineProxy = null;

            ArrayList buckets = null;

            try
            {
                engineProxy = new EngineProxy(parentModule, handleId, parentProjectFullFileName, projectFileOfTaskNode, loggingServices, buildEventContext);
                List<string> taskParameterValues = CreateListOfParameterValues();
                buckets = BatchingEngine.PrepareBatchingBuckets(taskNode, taskParameterValues, lookup);

                lookupHash = null;
                // Only create a hash table if there are more than one bucket as this is the only time a property can be overridden
                if (buckets.Count > 1)
                {
                    lookupHash = Utilities.CreateTableIfNecessary((Hashtable)null);
                }
		
		// Loop through each of the batch buckets and execute them one at a time
                for (int i=0; i < buckets.Count; i++)
                {
                    // Execute the batch bucket, pass in which bucket we are executing so that we know when to get a new taskId for the bucket.
                    taskExecutedSuccessfully = ExecuteBucket(engineProxy, (ItemBucket)buckets[i], i, howToExecuteTask);
                    if (!taskExecutedSuccessfully)
                    {
                        break;
                    }
                }
            }
            finally
            {
                // Remove the AssemblyResolve handler in the default AppDomain, we are done with the task.
                if (resolver != null)
                {
                    resolver.RemoveHandler();
                }

                if (engineProxy != null)
                {
                    engineProxy.MarkAsInActive();
                }

                // Now all task batches are done, apply all item adds to the outer 
                // target batch; we do this even if the task wasn't found (in that case,
                // no items or properties will have been added to the scope)
                if (buckets != null)
                {
                    foreach (ItemBucket bucket in buckets)
                    {
                        bucket.Lookup.LeaveScope();
                    }
                }
            }

            return taskExecutedSuccessfully;
        }