github.com/CycloneDX/sbom-utility@v0.16.0/cmd/validate_cdx_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  /*
     3   * Licensed to the Apache Software Foundation (ASF) under one or more
     4   * contributor license agreements.  See the NOTICE file distributed with
     5   * this work for additional information regarding copyright ownership.
     6   * The ASF licenses this file to You under the Apache License, Version 2.0
     7   * (the "License"); you may not use this file except in compliance with
     8   * the License.  You may obtain a copy of the License at
     9   *
    10   *     http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package cmd
    20  
    21  import "testing"
    22  
    23  // Consolidate test file name declarations
    24  const (
    25  	// CycloneDX - Test versioned documents meet min. schema requirements
    26  	TEST_CDX_1_3_MIN_REQUIRED = "test/cyclonedx/cdx-1-3-min-required.json"
    27  	TEST_CDX_1_4_MIN_REQUIRED = "test/cyclonedx/cdx-1-4-min-required.json"
    28  	TEST_CDX_1_5_MIN_REQUIRED = "test/cyclonedx/cdx-1-5-min-required.json"
    29  	TEST_CDX_1_6_MIN_REQUIRED = "test/cyclonedx/1.6/cdx-1-6-min-required.json"
    30  )
    31  
    32  // Tests for MLBOM subtypes
    33  const (
    34  	TEST_CDX_1_6_MACHINE_LEARNING_BOM = "test/cyclonedx/1.6/cdx-1-6-valid-mlbom-environmental-considerations.json"
    35  )
    36  
    37  // Tests for CBOM subtypes
    38  const (
    39  	TEST_CDX_1_6_CRYPTO_BOM = "test/cyclonedx/1.6/cdx-1-6-valid-cbom-full-1.6.json"
    40  )
    41  
    42  // Mature SBOMs used to test various schemas and queries
    43  const (
    44  	TEST_CDX_1_3_MATURE_EXAMPLE_1_BASE = "test/cyclonedx/cdx-1-3-mature-example-1.json"
    45  	TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE = "test/cyclonedx/cdx-1-4-mature-example-1.json"
    46  	TEST_CDX_1_5_MATURE_EXAMPLE_1_BASE = "test/cyclonedx/cdx-1-5-mature-example-1.json"
    47  )
    48  
    49  const (
    50  	// (invalid) schema tests
    51  	TEST_SCHEMA_CDX_1_3_INVALID_LICENSE_CHOICE = "test/cyclonedx/cdx-1-3-invalid-license-choice-oneof.json"
    52  	TEST_SCHEMA_CDX_1_3_INVALID_LICENSE_ID     = "test/cyclonedx/cdx-1-3-invalid-spdx-license-id.json"
    53  	TEST_SCHEMA_CDX_1_4_INVALID_LICENSE_ID     = "test/cyclonedx/cdx-1-3-invalid-spdx-license-id.json"
    54  	TEST_SCHEMA_CDX_1_4_INVALID_EMAIL_FORMAT   = "test/cyclonedx/cdx-1-4-invalid-email-format.json"
    55  )
    56  
    57  // Copied from CycloneDX spec. repo.
    58  // See: https://github.com/CycloneDX/specification/tree/master/tools/src/test/resources/1.6
    59  const (
    60  	TEST_CDX_SPEC_1_6_VALID_BOM             = "test/cyclonedx/1.6/specification/valid-bom-1.6.json"
    61  	TEST_CDX_SPEC_1_6_VALID_ANNOTATION      = "test/cyclonedx/1.6/specification/valid-annotation-1.6.json"
    62  	TEST_CDX_SPEC_1_6_VALID_ATTESTATION     = "test/cyclonedx/1.6/specification/valid-attestation-1.6.json"
    63  	TEST_CDX_SPEC_1_6_VALID_COMPONENT_HASH  = "test/cyclonedx/1.6/specification/valid-component-hashes-1.6.json"
    64  	TEST_CDX_SPEC_1_6_VALID_COMPONENT_IDS   = "test/cyclonedx/1.6/specification/valid-component-identifiers-1.6.json"
    65  	TEST_CDX_SPEC_1_6_VALID_SWID            = "test/cyclonedx/1.6/specification/valid-component-swid-1.6.json"
    66  	TEST_CDX_SPEC_1_6_VALID_SWID_FULL       = "test/cyclonedx/1.6/specification/valid-component-swid-full-1.6.json"
    67  	TEST_CDX_SPEC_1_6_VALID_COMPONENT_TYPES = "test/cyclonedx/1.6/specification/valid-component-types-1.6.json"
    68  	TEST_CDX_SPEC_1_6_VALID_CRYPTO_IMPL     = "test/cyclonedx/1.6/specification/valid-cryptography-implementation-1.6.json"
    69  	TEST_CDX_SPEC_1_6_VALID_EVIDENCE        = "test/cyclonedx/1.6/specification/valid-evidence-1.6.json"
    70  	TEST_CDX_SPEC_1_6_VALID_LICENSE_EXP     = "test/cyclonedx/1.6/specification/valid-license-expression-1.6.json"
    71  	TEST_CDX_SPEC_1_6_VALID_LICENSING       = "test/cyclonedx/1.6/specification/valid-license-licensing-1.6.json"
    72  	TEST_CDX_SPEC_1_6_VALID_ML              = "test/cyclonedx/1.6/specification/valid-machine-learning-1.6.json"
    73  	TEST_CDX_SPEC_1_6_VALID_ML_ENV          = "test/cyclonedx/1.6/specification/valid-machine-learning-considerations-env-1.6.json"
    74  	TEST_CDX_SPEC_1_6_VALID_METADATA_TOOL   = "test/cyclonedx/1.6/specification/valid-metadata-tool-1.6.json"
    75  	TEST_CDX_SPEC_1_6_VALID_SAASBOM         = "test/cyclonedx/1.6/specification/valid-saasbom-1.6.json"
    76  	TEST_CDX_SPEC_1_6_VALID_VULNERABILITY   = "test/cyclonedx/1.6/specification/valid-vulnerability-1.6.json"
    77  )
    78  
    79  // -----------------------------------------------------------
    80  // CycloneDX - Min. requirement & Mature tests
    81  // -----------------------------------------------------------
    82  
    83  func TestValidateCdx13MinRequiredBasic(t *testing.T) {
    84  	vti := NewValidateTestInfoMinimum(TEST_CDX_1_3_MIN_REQUIRED)
    85  	innerTestValidate(t, *vti)
    86  }
    87  
    88  func TestValidateCdx14MinRequiredBasic(t *testing.T) {
    89  	vti := NewValidateTestInfoMinimum(TEST_CDX_1_4_MIN_REQUIRED)
    90  	innerTestValidate(t, *vti)
    91  }
    92  
    93  func TestValidateCdx15MinRequiredBasic(t *testing.T) {
    94  	vti := NewValidateTestInfoMinimum(TEST_CDX_1_5_MIN_REQUIRED)
    95  	innerTestValidate(t, *vti)
    96  }
    97  
    98  func TestValidateCdx16MinRequiredBasic(t *testing.T) {
    99  	vti := NewValidateTestInfoMinimum(TEST_CDX_1_6_MIN_REQUIRED)
   100  	innerTestValidate(t, *vti)
   101  }
   102  
   103  func TestValidateCdx13Mature(t *testing.T) {
   104  	vti := NewValidateTestInfoMinimum(TEST_CDX_1_3_MATURE_EXAMPLE_1_BASE)
   105  	innerTestValidate(t, *vti)
   106  }
   107  
   108  func TestValidateCdx14MMature(t *testing.T) {
   109  	vti := NewValidateTestInfoMinimum(TEST_CDX_1_4_MATURE_EXAMPLE_1_BASE)
   110  	innerTestValidate(t, *vti)
   111  }
   112  
   113  func TestValidateCdx15Mature(t *testing.T) {
   114  	vti := NewValidateTestInfoMinimum(TEST_CDX_1_5_MATURE_EXAMPLE_1_BASE)
   115  	innerTestValidate(t, *vti)
   116  }
   117  
   118  // Test BOM variants (e.g., MLBOM, CBOM, etc.)
   119  func TestValidateCdx16MachineLearningBOM(t *testing.T) {
   120  	vti := NewValidateTestInfoMinimum(TEST_CDX_1_6_MACHINE_LEARNING_BOM)
   121  	innerTestValidate(t, *vti)
   122  }
   123  
   124  func TestValidateCdx16CryptographicBOM(t *testing.T) {
   125  	vti := NewValidateTestInfoMinimum(TEST_CDX_1_6_CRYPTO_BOM)
   126  	innerTestValidate(t, *vti)
   127  }
   128  
   129  // -----------------------------------------------------------
   130  // CycloneDX - (invalid) schema tests
   131  // -----------------------------------------------------------
   132  // NOTE: Schema errors do not have an "inner error", but return "[]gojsonschema.ResultError"
   133  // This means that these "errors" ARE NOT surfaced in the error return from Validate(); instead,
   134  // a `[]gojsonschema.ResultError` (custom error) is returned in the "results" array
   135  // -----------------------------------------------------------
   136  
   137  // Ensure invalid "id" in a License object is caught (i.e., "UNKNOWN" is not a valid SPDX ID value)
   138  func TestValidateSchemaCdx13InvalidSPDXLicenseId(t *testing.T) {
   139  	SCHEMA_ERROR_TYPE := "enum"
   140  	SCHEMA_ERROR_FIELD := "components.1.licenses.0.license.id"
   141  	SCHEMA_ERROR_VALUE := "UNKNOWN"
   142  
   143  	innerTestSchemaErrorAndErrorResults(t,
   144  		TEST_SCHEMA_CDX_1_3_INVALID_LICENSE_ID,
   145  		SCHEMA_VARIANT_NONE,
   146  		SCHEMA_ERROR_TYPE,
   147  		SCHEMA_ERROR_FIELD,
   148  		SCHEMA_ERROR_VALUE)
   149  }
   150  
   151  // (v1.4+) Ensure invalid email value (format) is caught (i.e., type not "idn-email")
   152  func TestValidateSchemaCdx14InvalidEmailFormat(t *testing.T) {
   153  	SCHEMA_ERROR_TYPE := "format"
   154  	SCHEMA_ERROR_FIELD := "metadata.supplier.contact.0.email"
   155  	SCHEMA_ERROR_VALUE := "https://acme.com"
   156  
   157  	innerTestSchemaErrorAndErrorResults(t,
   158  		TEST_SCHEMA_CDX_1_4_INVALID_EMAIL_FORMAT,
   159  		SCHEMA_VARIANT_NONE,
   160  		SCHEMA_ERROR_TYPE,
   161  		SCHEMA_ERROR_FIELD,
   162  		SCHEMA_ERROR_VALUE)
   163  }
   164  
   165  // (v1.2+) Ensure invalid LicenseChoice object is caught (i.e., has BOTH an "id" and "name")
   166  func TestValidateSchemaCdx13InvalidLicenseChoice(t *testing.T) {
   167  	SCHEMA_ERROR_TYPE := "number_one_of"
   168  	SCHEMA_ERROR_FIELD := "metadata.component.licenses.0.license"
   169  	// Note: the value returned is not a simple string so do not test this
   170  	// field of the error results.
   171  	SCHEMA_ERROR_VALUE := ""
   172  
   173  	innerTestSchemaErrorAndErrorResults(t,
   174  		TEST_SCHEMA_CDX_1_3_INVALID_LICENSE_CHOICE,
   175  		SCHEMA_VARIANT_NONE,
   176  		SCHEMA_ERROR_TYPE,
   177  		SCHEMA_ERROR_FIELD,
   178  		SCHEMA_ERROR_VALUE)
   179  }