BuildComponentFactory__WhenCallingTaskWith_UpdateSteamWorkshopItem__ShouldReturnUpdateSteamWorkshopItemTaskBuilder()
        {
            BuildComponentFactory sut = new BuildComponentFactory();

            ITaskBuilder taskBuilder = sut.Task("UpdateSteamWorkshopItem");

            Assert.IsInstanceOfType(taskBuilder, typeof(UpdateSteamWorkshopItemTaskBuilder));
        }
        public void BuildComponentFactory__WhenCallingTaskWith_SoftCopy__ShouldReturnCopyTaskBuilder()
        {
            BuildComponentFactory sut = new BuildComponentFactory();

            ITaskBuilder taskBuilder = sut.Task("SoftCopy");

            Assert.IsInstanceOfType(taskBuilder, typeof(CopyTaskBuilder));
        }
        public void BuildComponentFactory__WhenCallingTaskWith_RunProgram__ShouldReturnRunProcessTaskBuilder()
        {
            BuildComponentFactory sut = new BuildComponentFactory();

            ITaskBuilder taskBuilder = sut.Task("RunProgram");

            Assert.IsInstanceOfType(taskBuilder, typeof(RunProcessTaskBuilder));
        }
        public void BuildComponentFactory__WhenCallingMakeProject__ShouldReturnProject()
        {
            BuildComponentFactory sut = new BuildComponentFactory();

            IProject project = sut.MakeProject();

            Assert.IsInstanceOfType(project, typeof(Project));
        }
        public void BuildComponentFactory__WhenCallingMakeJob__ShouldReturnJob()
        {
            BuildComponentFactory sut = new BuildComponentFactory();

            IJob job = sut.MakeJob("job");

            Assert.IsInstanceOfType(job, typeof(Job));
            Assert.AreEqual("job", job.Name);
        }
Пример #6
0
        /// <summary>
        /// This handles merging of the custom component configurations into the configuration file including
        /// dependencies.
        /// </summary>
        /// <param name="id">The ID of the component to merge</param>
        /// <param name="factory">The build component factory</param>
        /// <param name="rootNode">The root container node</param>
        /// <param name="configNode">The configuration node to merge</param>
        /// <param name="isConceptualConfig">True if this is a conceptual content configuration file or false if
        /// it is a reference build configuration file.</param>
        /// <param name="mergeStack">A stack used to check for circular build component dependencies.  Pass null
        /// on the first non-recursive call.</param>
        private void MergeComponent(string id, BuildComponentFactory factory, XmlNode rootNode, XmlNode configNode,
                                    bool isConceptualConfig, Stack <string> mergeStack)
        {
            ComponentPlacement position;
            XmlNodeList        matchingNodes;
            XmlNode            node;
            string             replaceId;

            // Merge dependent component configurations first
            if (factory.Dependencies.Any())
            {
                if (mergeStack == null)
                {
                    mergeStack = new Stack <string>();
                }

                foreach (string dependency in factory.Dependencies)
                {
                    node = rootNode.SelectSingleNode("component[@id='" + dependency + "']");

                    // If it's already there or would create a circular dependency, ignore it
                    if (node != null || mergeStack.Contains(dependency))
                    {
                        continue;
                    }

                    // Add the dependency with a default configuration
                    if (!buildComponents.TryGetValue(dependency, out BuildComponentFactory dependencyFactory))
                    {
                        throw new BuilderException("BE0023", String.Format(CultureInfo.CurrentCulture,
                                                                           "The project contains a reference to a custom build component '{0}' that has a " +
                                                                           "dependency '{1}' that could not be found.", id, dependency));
                    }

                    node          = rootNode.OwnerDocument.CreateDocumentFragment();
                    node.InnerXml = substitutionTags.TransformText(dependencyFactory.DefaultConfiguration);

                    this.ReportProgress("    Merging '{0}' dependency for '{1}'", dependency, id);

                    mergeStack.Push(dependency);
                    this.MergeComponent(dependency, dependencyFactory, rootNode, node, isConceptualConfig, mergeStack);
                    mergeStack.Pop();
                }
            }

            position = (!isConceptualConfig) ? factory.ReferenceBuildPlacement : factory.ConceptualBuildPlacement;

            // Find all matching components by ID
            replaceId     = position.Id;
            matchingNodes = rootNode.SelectNodes("component[@id='" + replaceId + "']");

            // If replacing another component, search for that by ID and replace it if found
            if (position.Placement == PlacementAction.Replace)
            {
                if (matchingNodes.Count < position.AdjustedInstance)
                {
                    this.ReportProgress("    Could not find configuration '{0}' (instance {1}) to replace with " +
                                        "configuration for '{2}' so it will be omitted.", replaceId, position.AdjustedInstance, id);

                    // If it's a dependency, that's a problem
                    if (mergeStack.Count != 0)
                    {
                        throw new BuilderException("BE0024", "Unable to add dependent configuration: " + id);
                    }

                    return;
                }

                rootNode.ReplaceChild(configNode, matchingNodes[position.AdjustedInstance - 1]);

                this.ReportProgress("    Replaced configuration for '{0}' (instance {1}) with configuration " +
                                    "for '{2}'", replaceId, position.AdjustedInstance, id);

                // Adjust instance values on matching components
                foreach (var component in buildComponents.Values)
                {
                    if (!isConceptualConfig)
                    {
                        if (component.ReferenceBuildPlacement.Id == replaceId &&
                            component.ReferenceBuildPlacement.AdjustedInstance > position.AdjustedInstance)
                        {
                            component.ReferenceBuildPlacement.AdjustedInstance--;
                        }
                    }
                    else
                    if (component.ConceptualBuildPlacement.Id == replaceId &&
                        component.ConceptualBuildPlacement.AdjustedInstance > position.AdjustedInstance)
                    {
                        component.ConceptualBuildPlacement.AdjustedInstance--;
                    }
                }

                return;
            }

            // See if the configuration already exists.  If so, replace it.  We'll assume it's already in the
            // correct location.
            node = rootNode.SelectSingleNode("component[@id='" + id + "']");

            if (node != null)
            {
                this.ReportProgress("    Replacing default configuration for '{0}' with the custom configuration", id);
                rootNode.ReplaceChild(configNode, node);
                return;
            }

            // Create the node and add it in the correct location
            switch (position.Placement)
            {
            case PlacementAction.Start:
                rootNode.InsertBefore(configNode, rootNode.ChildNodes[0]);
                this.ReportProgress("    Added configuration for '{0}' to the start of the configuration file", id);
                break;

            case PlacementAction.End:
                rootNode.InsertAfter(configNode,
                                     rootNode.ChildNodes[rootNode.ChildNodes.Count - 1]);
                this.ReportProgress("    Added configuration for '{0}' to the end of the configuration file", id);
                break;

            case PlacementAction.Before:
                if (matchingNodes.Count < position.AdjustedInstance)
                {
                    this.ReportProgress("    Could not find configuration '{0}' (instance {1}) to add " +
                                        "configuration for '{2}' so it will be omitted.", replaceId, position.AdjustedInstance, id);
                }
                else
                {
                    rootNode.InsertBefore(configNode, matchingNodes[position.AdjustedInstance - 1]);
                    this.ReportProgress("    Added configuration for '{0}' before '{1}' (instance {2})",
                                        id, replaceId, position.AdjustedInstance);
                }
                break;

            default:        // After
                if (matchingNodes.Count < position.AdjustedInstance)
                {
                    this.ReportProgress("    Could not find configuration '{0}' (instance {1}) to add " +
                                        "configuration for '{2}' so it will be omitted.", replaceId, position.AdjustedInstance, id);
                }
                else
                {
                    rootNode.InsertAfter(configNode, matchingNodes[position.AdjustedInstance - 1]);
                    this.ReportProgress("    Added configuration for '{0}' after '{1}' (instance {2})",
                                        id, replaceId, position.AdjustedInstance);
                }
                break;
            }
        }
        public void BuildComponentFactory__WhenCallingTaskWithUnknownTaskType__ShouldThrowInvalidOperationException()
        {
            BuildComponentFactory sut = new BuildComponentFactory();

            sut.Task("Unknown");
        }