public Document run() throws ParserConfigurationException, IOException, SAXException, TransformerException {
        DocumentBuilder docBuilder = XML.getDocumentBuilder();
        Document document = docBuilder.parse(new InputSource(xmlInput));
        return execute(document);
    }
@Test
    public void testPreProcessing() throws Exception {
        String expectedDev =
                """
                <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                <!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
                <services xmlns:deploy="vespa" xmlns:preprocess="properties" version="1.0">
                    <admin version="2.0">
                        <adminserver hostalias="node0"/>
                    </admin>
                    <content id="foo" version="1.0">
                      <redundancy>1</redundancy>
                      <documents>
                        <document mode="index" type="music.sd"/>
                      </documents>
                      <nodes>
                        <node distribution-key="0" hostalias="node0"/>
                      </nodes>
                    </content>
                    <container id="stateless" version="1.0">
                      <search/>
                      <component bundle="foobundle" class="MyFoo" id="foo"/>
                      <component bundle="foobundle" class="TestBar" id="bar"/>
                      <nodes>
                        <node hostalias="node0" baseport="5000"/>
                      </nodes>
                    </container>
                </services>""";
        TestBase.assertDocument(expectedDev,
                                new XmlPreProcessor(appDir,
                                                    services,
                                                    InstanceName.defaultName(),
                                                    Environment.dev,
                                                    RegionName.defaultName(),
                                                    Cloud.defaultCloud().name(),
                                                    Tags.empty()).run());

        // Difference from dev: node1
        // Difference from dev: no TestBar
        String expectedStaging =
                """
                <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                <!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
                <services xmlns:deploy="vespa" xmlns:preprocess="properties" version="1.0">
                    <admin version="2.0">
                        <adminserver hostalias="node0"/>
                    </admin>
                    <content id="foo" version="1.0">
                      <redundancy>1</redundancy>
                      <documents>
                        <document mode="index" type="music.sd"/>
                      </documents>
                      <nodes>
                        <node distribution-key="0" hostalias="node0"/>
                      </nodes>
                    </content>
                    <container id="stateless" version="1.0">
                      <search/>
                      <component bundle="foobundle" class="MyFoo" id="foo"/>
                      <nodes>
                        <node hostalias="node0" baseport="5000"/>
                      </nodes>
                    </container>
                </services>""";
        TestBase.assertDocument(expectedStaging,
                                new XmlPreProcessor(appDir,
                                                    services,
                                                    InstanceName.defaultName(),
                                                    Environment.staging,
                                                    RegionName.defaultName(),
                                                    Cloud.defaultCloud().name(),
                                                    Tags.empty()).run());

        String expectedPerfUsWest =
                """
                <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                <!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
                <services xmlns:deploy="vespa" xmlns:preprocess="properties" version="1.0">
                    <admin version="2.0">
                        <adminserver hostalias="node0"/>
                    </admin>
                    <content id="foo" version="1.0">
                      <redundancy>1</redundancy>
                      <documents>
                        <document mode="index" type="music.sd"/>
                      </documents>
                      <nodes>
                        <node distribution-key="0" hostalias="node0"/>
                      </nodes>
                    </content>
                    <container id="stateless" version="1.0">
                      <search/>
                      <component bundle="foobundle" class="MyFoo" id="foo"/>
                      <nodes>
                        <node hostalias="node0" baseport="5000"/>
                      </nodes>
                    </container>
                </services>""";
        TestBase.assertDocument(expectedPerfUsWest,
                                new XmlPreProcessor(appDir,
                                                    services,
                                                    InstanceName.defaultName(),
                                                    Environment.perf,
                                                    RegionName.from("us-west"),
                                        Cloud.defaultCloud().name(), Tags.empty()).run());

        String expectedPerfUsEastAndCentral =
                """
                <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                <!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
                <services xmlns:deploy="vespa" xmlns:preprocess="properties" version="1.0">
                    <admin version="2.0">
                        <adminserver hostalias="node0"/>
                    </admin>
                    <content id="foo" version="1.0">
                      <thread count="128"/>
                      <redundancy>1</redundancy>
                      <documents>
                        <document mode="index" type="music.sd"/>
                      </documents>
                      <nodes>
                        <node distribution-key="0" hostalias="node0"/>
                      </nodes>
                    </content>
                    <container id="stateless" version="1.0">
                      <search/>
                      <component bundle="foobundle" class="MyFoo" id="foo"/>
                      <nodes>
                        <node hostalias="node0" baseport="5000"/>
                      </nodes>
                    </container>
                </services>""";
        TestBase.assertDocument(expectedPerfUsEastAndCentral,
                                new XmlPreProcessor(appDir,
                                                    services,
                                                    InstanceName.defaultName(),
                                                    Environment.perf,
                                                    RegionName.from("us-east"),
                                        Cloud.defaultCloud().name(), Tags.empty()).run());
        TestBase.assertDocument(expectedPerfUsEastAndCentral,
                                new XmlPreProcessor(appDir,
                                                    services,
                                                    InstanceName.defaultName(),
                                                    Environment.perf,
                                                    RegionName.from("us-central"),
                                        Cloud.defaultCloud().name(), Tags.empty()).run());

        String expectedProdUsWest =
                """
                <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                <!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
                <services xmlns:deploy="vespa" xmlns:preprocess="properties" version="1.0">
                    <admin version="2.0">
                        <adminserver hostalias="node0"/>
                    </admin>
                    <content id="foo" version="1.0">
                      <redundancy>1</redundancy>
                      <documents>
                        <document mode="index" type="music.sd"/>
                      </documents>
                      <nodes>
                        <node distribution-key="0" hostalias="node0"/>
                        <node distribution-key="1" hostalias="node1"/>
                        <node distribution-key="2" hostalias="node2"/>
                      </nodes>
                    </content>
                    <container id="stateless" version="1.0">
                      <search>
                        <chain id="common">
                          <searcher id="MySearcher1"/>
                          <searcher id="MySearcher2"/>
                        </chain>
                      </search>
                      <component bundle="foobundle" class="MyFoo" id="foo"/>
                      <component bundle="foobundle" class="ProdBar" id="bar"/>
                      <component bundle="foobundle" class="ProdBaz" id="baz"/>
                      <nodes>
                        <node hostalias="node0" baseport="5001"/>
                      </nodes>
                    </container>
                </services>""";
        TestBase.assertDocument(expectedProdUsWest,
                                new XmlPreProcessor(appDir,
                                                    services,
                                                    InstanceName.defaultName(),
                                                    Environment.prod,
                                                    RegionName.from("us-west"),
                                        Cloud.defaultCloud().name(), Tags.empty()).run());

        String expectedProdUsEastAndCentral =
                """
                <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                <!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
                <services xmlns:deploy="vespa" xmlns:preprocess="properties" version="1.0">
                    <admin version="2.0">
                        <adminserver hostalias="node1"/>
                    </admin>
                    <content id="foo" version="1.0">
                      <thread count="128"/>
                      <redundancy>1</redundancy>
                      <documents>
                        <document mode="index" type="music.sd"/>
                      </documents>
                      <nodes>
                        <node distribution-key="0" hostalias="node0"/>
                        <node distribution-key="1" hostalias="node1"/>
                      </nodes>
                    </content>
                    <container id="stateless" version="1.0">
                      <search>
                        <chain id="common">
                          <searcher id="MySearcher1"/>
                          <searcher id="MySearcher2"/>
                        </chain>
                      </search>
                      <component bundle="foobundle" class="MyFoo" id="foo"/>
                      <component bundle="foobundle" class="ProdBar" id="bar"/>
                      <component bundle="foobundle" class="ProdBaz" id="baz"/>
                      <nodes>
                        <node hostalias="node0" baseport="5002"/>
                      </nodes>
                    </container>
                </services>""";
        TestBase.assertDocument(expectedProdUsEastAndCentral,
                                new XmlPreProcessor(appDir,
                                                    services,
                                                    InstanceName.defaultName(),
                                                    Environment.prod,
                                                    RegionName.from("us-east"),
                                        Cloud.defaultCloud().name(), Tags.empty()).run());
        TestBase.assertDocument(expectedProdUsEastAndCentral,
                                new XmlPreProcessor(appDir,
                                                    services,
                                                    InstanceName.defaultName(),
                                                    Environment.prod,
                                                    RegionName.from("us-central"),
                                        Cloud.defaultCloud().name(), Tags.empty()).run());
    }