<?xml version="1.0"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      https://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<project name="componentbom-test" default="antunit">

  <import file="shared.xml" />

  <checksum property="sha256hash" file="${antlib.location}" algorithm="SHA-256"/>

  <target name="testToolMetadataInJsonFormat">
    <cdx:componentbom outputdirectory="${output}"
                      xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="testname">
        <file file="${antlib.location}"/>
      </component>
    </cdx:componentbom>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.json"
        value='"name" : "ant-cyclonedx"'/>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.json"
        value='"version" : "${artifact.version}"'/>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.json"
        value='"description" : "Apache CycloneDX Antlib"'/>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.json"
        value='"alg" : "SHA-256"'/>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.json"
        value='"content" : "${sha256hash}"'/>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.json"
        value='"url" : "https://gitbox.apache.org/repos/asf/ant-antlibs-cyclonedx.git"'/>
  </target>

  <target name="testToolMetadataInXmlFormat" depends="testMulipleTools">
    <cdx:component name="testname" id="test"
                   xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <file file="${antlib.location}"/>
    </cdx:component>
    <cdx:componentbom outputdirectory="${output}" format="xml"
                      xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component refid="test"/>
    </cdx:componentbom>
    <xmlproperty file="${output}/bom.xml"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.lifecycles.lifecycle.phase"
        value="build"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component.name"
        value="ant-cyclonedx"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component.group"
        value="org.apache.ant"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component.version"
        value="${artifact.version}"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component(type)"
        value="library"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component.description"
        value="Apache CycloneDX Antlib"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component.manufacturer.name"
        value="Apache Ant Project Management Committee"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component.manufacturer.url"
        value="https://ant.apache.org/"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component.supplier.name"
        value="Apache Ant Project Management Committee"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component.supplier.url"
        value="https://ant.apache.org/"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component.licenses.license.id"
        value="Apache-2.0"/>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.xml"
        value='&lt;hash alg="SHA-256"&gt;${sha256hash}&lt;/hash&gt;'/>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.xml"
        value='&lt;url&gt;https://gitbox.apache.org/repos/asf/ant-antlibs-cyclonedx.git&lt;/url&gt;'/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.tools.components.component.publisher"
        value="The Apache Software Foundation"/>
  </target>

  <target name="testMulipleTools">
    <cdx:componentbom
        bomName="multi"
        outputdirectory="${output}"
        format="xml"
        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="test"/>
      <toolComponent name="extra-tool"/>
    </cdx:componentbom>
    <xmlproperty file="${output}/multi.xml" prefix="multi"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="multi.bom.metadata.tools.components.component.name"
        value="ant-cyclonedx,extra-tool"/>
  </target>

  <target name="testSupplierAndManufacturerInMeta">
    <cdx:organization name="Example" id="example"
                      xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <url url="https://example.org/"/>
    </cdx:organization>

    <cdx:componentbom outputdirectory="${output}" format="XML"
                      xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <manufacturer refid="example"/>
      <supplier name="Example 2">
        <url url="https://example.com/"/>
      </supplier>
      <component name="testname"/>
    </cdx:componentbom>
    <xmlproperty file="${output}/bom.xml"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.manufacturer.name"
        value="Example"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.manufacturer.url"
        value="https://example.org/"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.supplier.name"
        value="Example 2"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.supplier.url"
        value="https://example.com/"/>

    <cdx:componentbom outputdirectory="${output}" format="xml"
                      useComponentSupplier="true"
                      xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="testname">
        <supplier name="Example 2">
          <url url="https://example.com/"/>
        </supplier>
      </component>
    </cdx:componentbom>
    <xmlproperty file="${output}/bom.xml"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.supplier.name"
        value="Example 2"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.supplier.url"
        value="https://example.com/"/>

    <cdx:componentbom outputdirectory="${output}" format="xml"
                      bomname="manufacturer"
                      useComponentManufacturer="true"
                      xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="testname">
        <manufacturer name="Example 2">
          <url url="https://example.com/"/>
        </manufacturer>
      </component>
    </cdx:componentbom>
    <xmlproperty file="${output}/manufacturer.xml" prefix="m"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="m.bom.metadata.manufacturer.name"
        value="Example 2"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="m.bom.metadata.manufacturer.url"
        value="https://example.com/"/>

    <au:expectfailure expectedMessage="useComponentSupplier is true but component supplier is null"
        xmlns:au="antlib:org.apache.ant.antunit">
      <cdx:componentbom format="xml"
                        useComponentSupplier="true"
                        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
        <component name="testname"/>
      </cdx:componentbom>
    </au:expectfailure>

    <au:expectfailure expectedMessage="can't use component's supplier when there is an explicit supplier"
        xmlns:au="antlib:org.apache.ant.antunit">
      <cdx:componentbom format="xml"
                        useComponentSupplier="true"
                        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
        <component name="testname">
          <supplier name="Foo"/>
        </component>
        <supplier name="Foo"/>
      </cdx:componentbom>
    </au:expectfailure>

    <au:expectfailure expectedMessage="useComponentManufacturer is true but component manufacturer is null"
        xmlns:au="antlib:org.apache.ant.antunit">
      <cdx:componentbom format="xml"
                        useComponentManufacturer="true"
                        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
        <component name="testname"/>
      </cdx:componentbom>
    </au:expectfailure>

    <au:expectfailure expectedMessage="can't use component's manufacturer when there is an explicit manufacturer"
        xmlns:au="antlib:org.apache.ant.antunit">
      <cdx:componentbom format="xml"
                        useComponentManufacturer="true"
                        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
        <component name="testname">
          <manufacturer name="Foo"/>
        </component>
        <manufacturer name="Foo"/>
      </cdx:componentbom>
    </au:expectfailure>
  </target>

  <target name="testOutputDirectoryDefaultsToBaseDir">
    <cdx:componentbom format="xml" xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="testname"/>
    </cdx:componentbom>
    <condition property="file-exists">
      <available file="bom.xml"/>
    </condition>
    <delete file="bom.xml" failonerror="false" deleteonexit="true"/>
    <au:assertPropertySet name="file-exists"
                          xmlns:au="antlib:org.apache.ant.antunit"/>
  </target>

  <target name="testOutputDirectoryMustExist">
    <au:expectfailure expectedMessage="outputDirectory must point to a directory"
        xmlns:au="antlib:org.apache.ant.antunit">
      <cdx:componentbom outputdirectory="foo" format="xml"
                        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
        <component name="testname"/>
      </cdx:componentbom>
    </au:expectfailure>
  </target>

  <target name="testOutputDirectoryMustBeADirectory">
    <au:expectfailure expectedMessage="outputDirectory must point to a directory"
        xmlns:au="antlib:org.apache.ant.antunit">
      <cdx:componentbom outputdirectory="${ant.file}" format="xml"
                        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
        <component name="testname"/>
      </cdx:componentbom>
    </au:expectfailure>
  </target>

  <target name="testComponentIsRequired">
    <au:expectfailure expectedMessage="nested component element is required"
        xmlns:au="antlib:org.apache.ant.antunit">
      <cdx:componentbom outputdirectory="${output}" format="xml"
                        xmlns:cdx="antlib:org.apache.ant.cyclonedx"/>
    </au:expectfailure>
  </target>

  <target name="testOnlyOneComponentIsPermitted">
    <au:expectfailure expectedMessage="only one nested component element is permitted"
        xmlns:au="antlib:org.apache.ant.antunit">
      <cdx:componentbom outputdirectory="${output}" format="xml"
                        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
        <component/>
        <component/>
      </cdx:componentbom>
    </au:expectfailure>
  </target>

  <target name="testSpecVersionAsVersionString">
    <cdx:componentbom
        outputdirectory="${output}"
        format="json"
        specVersion="1.6"
        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="testname"/>
    </cdx:componentbom>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.json"
        value='"specVersion" : "1.6"'/>
  </target>

  <target name="testSpecVersionAsEnumValue">
    <cdx:componentbom
        outputdirectory="${output}"
        format="json"
        specVersion="VERSION_16"
        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="testname"/>
    </cdx:componentbom>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.json"
        value='"specVersion" : "1.6"'/>
  </target>

  <target name="testDependencies">
    <cdx:componentbom outputdirectory="${output}" format="xml"
                      xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="testname" group="org.example" version="1.0">
        <dependency bomRef="pkg:maven/org.example/dependency@1.0?type=jar"/>
      </component>
      <additionalComponent
          name="dependency" group="org.example" version="1.0">
        <dependency componentRef="transitve"/>
      </additionalComponent>
      <additionalComponent
          name="transitive-dependency" group="org.example"
          version="1.0" id="transitve"
          unknownDependencies="true"/>
      <additionalComponent name="empty" group="org.example" version="1.0"/>
    </cdx:componentbom>
    <xmlproperty file="${output}/bom.xml"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.dependencies.dependency(ref)"
        value="pkg:maven/org.example/testname@1.0?type=jar,pkg:maven/org.example/dependency@1.0?type=jar,pkg:maven/org.example/empty@1.0?type=jar"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.dependencies.dependency.dependency(ref)"
        value="pkg:maven/org.example/dependency@1.0?type=jar,pkg:maven/org.example/transitive-dependency@1.0?type=jar"/>
  </target>

  <target name="testNestedComponents">
    <cdx:componentbom outputdirectory="${output}" format="xml"
                      xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="testname" group="org.example" version="1.0">
        <component name="testname-child" group="org.example" version="1.0">
          <component name="testname-grand-child" group="org.example" version="1.0"/>
        </component>
      </component>
      <additionalComponent name="testname2" group="org.example" version="1.0">
        <component name="testname2-child" group="org.example" version="1.0">
          <component name="testname2-grand-child" group="org.example" version="1.0"/>
        </component>
      </additionalComponent>
    </cdx:componentbom>
    <xmlproperty file="${output}/bom.xml"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.component.components.component.name"
        value="testname-child"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.metadata.component.components.component.components.component.name"
        value="testname-grand-child"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.components.component.components.component.components.component.name"
        value="testname2-grand-child"/>
  </target>

  <target name="testNestedComponentDependencies">
    <cdx:componentbom outputdirectory="${output}" format="xml"
                      xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="testname" group="org.example" version="1.0" unknownDependencies="true">
        <component name="testname-child" group="org.example" version="1.0">
          <component name="testname-grand-child" group="org.example" version="1.0" unknownDependencies="true"/>
          <dependency bomref="pkg:maven/org.example/testname2-child@1.0?type=jar"/>
        </component>
      </component>
      <additionalComponent name="testname2" group="org.example" version="1.0" unknownDependencies="true">
        <component name="testname2-child" group="org.example" version="1.0" unknownDependencies="true">
          <component name="testname2-grand-child" group="org.example" version="1.0">
            <dependency bomref="pkg:maven/org.example/testname-grand-child@1.0?type=jar"/>
          </component>
        </component>
      </additionalComponent>
    </cdx:componentbom>
    <xmlproperty file="${output}/bom.xml"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.dependencies.dependency(ref)"
        value="pkg:maven/org.example/testname-child@1.0?type=jar,pkg:maven/org.example/testname2-grand-child@1.0?type=jar"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.dependencies.dependency.dependency(ref)"
        value="pkg:maven/org.example/testname2-child@1.0?type=jar,pkg:maven/org.example/testname-grand-child@1.0?type=jar"/>
  </target>

  <target name="testPureFileComponentsMustNotContainNonFileResources">
    <au:expectfailure expectedMessage="only file system resources are supported for pureFileComponents"
        xmlns:au="antlib:org.apache.ant.antunit">
      <cdx:componentbom outputdirectory="${output}" format="xml"
                        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
        <component name="testname"/>
        <pureFileComponents>
          <url url="https://example.org/"/>
        </pureFileComponents>
      </cdx:componentbom>
    </au:expectfailure>
  </target>

  <target name="testDependencyMustExist">
    <au:expectfailure expectedMessage="dependency 'test' is unknown"
        xmlns:au="antlib:org.apache.ant.antunit">
      <cdx:componentbom outputdirectory="${output}" format="xml"
                        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
        <component name="testname" bomref="foo">
          <dependency bomref="test"/>
        </component>
      </cdx:componentbom>
    </au:expectfailure>
  </target>

  <target name="testPureFileComponentsAddsFileComponents">
    <checksum property="ant.file.sha256" file="${ant.file}" algorithm="SHA-256"/>
    <cdx:componentbom outputdirectory="${output}" format="xml"
                      xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component name="testname"/>
      <pureFileComponents>
        <file file="${ant.file}"/>
      </pureFileComponents>
    </cdx:componentbom>
    <xmlproperty file="${output}/bom.xml"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.components.component.name"
        value="componentbom-test.xml"/>
    <au:assertPropertyEquals
        xmlns:au="antlib:org.apache.ant.antunit"
        name="bom.components.component(type)"
        value="file"/>
    <au:assertResourceContains
        xmlns:au="antlib:org.apache.ant.antunit"
        resource="${output}/bom.xml"
        value='&lt;hash alg="SHA-256"&gt;${ant.file.sha256}&lt;/hash&gt;'/>
  </target>

  <target name="testAntlibsOwnBom" depends="commonReferences">
    <cdx:componentbom
        bomName="ant-cyclonedx-${artifact.version}-cyclonedx"
        outputdirectory="${output}"
        format="all"
        useComponentSupplier="true"
        useComponentManufacturer="true"
        xmlns:cdx="antlib:org.apache.ant.cyclonedx">
      <component
          name="ant-cyclonedx"
          group="org.apache.ant"
          version="${artifact.version}"
          description="Apache CycloneDX Antlib"
          publisher="The Apache Software Foundation"
          supplierIsManufacturer="true">
        <file file="${antlib.location}"/>
        <supplier refid="ant-team"/>
        <license refid="apache-2"/>
        <externalReferenceSet refid="antlib-ext-refs"/>
        <dependency componentRef="ant"/>
        <dependency componentRef="cyclonedx-core"/>
      </component>
      <additionalComponent
          name="ant"
          group="org.apache.ant"
          version="1.10.17"
          isExternal="true"
          unknownDependencies="true"
          id="ant">
        <manufacturer refid="ant-team"/>
        <license refid="apache-2"/>
        <externalReference
            type="VCS"
            url="https://github.com/apache/ant"/>
        <externalReference
            type="WEBSITE"
            url="https://ant.apache.org/"/>
      </additionalComponent>
      <additionalComponent id="cyclonedx-core">
        <sbomLink>
          <file file="resources/cyclonedx-core-java-12.2.0-cyclonedx.json"/>
        </sbomLink>
      </additionalComponent>
      <license refid="apache-2"/>
    </cdx:componentbom>
    <au:assertFileExists
        xmlns:au="antlib:org.apache.ant.antunit"
        file="${output}/ant-cyclonedx-${artifact.version}-cyclonedx.json"/>
    <au:assertFileExists
        xmlns:au="antlib:org.apache.ant.antunit"
        file="${output}/ant-cyclonedx-${artifact.version}-cyclonedx.xml"/>
    <copy todir="${java.io.tmpdir}">
      <fileset dir="${output}" includes="ant-cyclonedx*"/>
    </copy>
  </target>
</project>
