Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support schema error results to be output in JSON format including custom format flags #40

Merged
merged 28 commits into from
Jun 26, 2023
Merged
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
47bbdcc
Create a framework for validation error special case handling
mrutkows Jun 16, 2023
2688048
Create a framework for validation error special case handling
mrutkows Jun 16, 2023
8369472
Adjust JSON output formatting as an array
mrutkows Jun 19, 2023
bfa6985
Use an ordered map to control JSON output marshaling order
mrutkows Jun 19, 2023
7776c34
Use an ordered map to control JSON output marshaling order
mrutkows Jun 19, 2023
09bf70a
Use an ordered map to control JSON output marshaling order
mrutkows Jun 19, 2023
fd9cba3
Use an ordered map to control JSON output marshaling order
mrutkows Jun 19, 2023
bc89b66
Separate format related functions into their own file
mrutkows Jun 20, 2023
086f09d
Separate format related functions into their own file
mrutkows Jun 20, 2023
55810a6
Format value for unique item error
mrutkows Jun 21, 2023
54449f2
Consolidate validation flags and use on top-level API call
mrutkows Jun 21, 2023
e3bf5c4
Adjust JSON error result output prefix and indent
mrutkows Jun 21, 2023
7d23529
Add validation test case for bad iri-format
mrutkows Jun 21, 2023
38511c1
Add validation test case for bad iri-format
mrutkows Jun 21, 2023
292a82d
Consolidate persistent command flags into a struct
mrutkows Jun 21, 2023
4ab94f6
represent array type, index and item as a map in json error results
mrutkows Jun 21, 2023
5b57e38
Support flag true|false on validate command
mrutkows Jun 21, 2023
a630b7e
Fix even more Sonatype errors that seem to chnage every time I touch …
mrutkows Jun 21, 2023
16f8ce6
Adjust help for validate given new formats/flags
mrutkows Jun 22, 2023
ff1c278
Update README to show validate JSON output and new flags
mrutkows Jun 22, 2023
7258d9e
buffer JSON output for unit tests
mrutkows Jun 22, 2023
577e945
Update the text format logic to mirror new json formatting
mrutkows Jun 23, 2023
b02cebc
Update the text format logic to mirror new json formatting
mrutkows Jun 23, 2023
bf72268
Update the text format logic to mirror new json formatting
mrutkows Jun 23, 2023
ac503d5
Streamline json and text formatting paths
mrutkows Jun 23, 2023
d646e3e
Adjust colorized indent to match normal indent
mrutkows Jun 26, 2023
62deaed
Add additional test assertions to validate # errs and error conext
mrutkows Jun 26, 2023
64af463
Assure forced schema file tests reset to default schema
mrutkows Jun 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
buffer JSON output for unit tests
Signed-off-by: Matt Rutkowski <mrutkows@us.ibm.com>
mrutkows committed Jun 22, 2023
commit 7258d9e54267aaf091fa34b9417ea1b47a71767d
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@ const (
MSG_FLAG_DEBUG = "enable debug logging"
MSG_FLAG_INPUT = "input filename (e.g., \"path/sbom.json\")"
MSG_FLAG_OUTPUT = "output filename"
MSG_FLAG_LOG_QUIET = "enable quiet logging mode (removes all information messages from console output); overrides other logging commands"
MSG_FLAG_LOG_QUIET = "enable quiet logging mode (removes all informational messages from console output); overrides other logging commands"
MSG_FLAG_LOG_INDENT = "enable log indentation of functional callstack"
MSG_FLAG_CONFIG_SCHEMA = "provide custom application schema configuration file (i.e., overrides default `config.json`)"
MSG_FLAG_CONFIG_LICENSE = "provide custom application license policy configuration file (i.e., overrides default `license.json`)"
39 changes: 24 additions & 15 deletions cmd/validate.go
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ package cmd
import (
"encoding/json"
"fmt"
"io"
"os"
"strings"

@@ -112,22 +113,21 @@ func validateCmdImpl(cmd *cobra.Command, args []string) error {
getLogger().Enter()
defer getLogger().Exit()

// TODO - support an output file for errors
// Create output writer
// outputFilename := utils.GlobalFlags.PersistentFlags.OutputFile
// outputFile, writer, err := createOutputFile(outputFilename)

// // use function closure to assure consistent error output based upon error type
// defer func() {
// // always close the output file
// if outputFile != nil {
// err = outputFile.Close()
// getLogger().Infof("Closed output file: `%s`", outputFilename)
// }
// }()
outputFilename := utils.GlobalFlags.PersistentFlags.OutputFile
outputFile, writer, err := createOutputFile(outputFilename)

// use function closure to assure consistent error output based upon error type
defer func() {
// always close the output file
if outputFile != nil {
err = outputFile.Close()
getLogger().Infof("Closed output file: `%s`", outputFilename)
}
}()

// invoke validate and consistently manage exit messages and codes
isValid, _, _, err := Validate(utils.GlobalFlags.PersistentFlags, utils.GlobalFlags.ValidateFlags)
isValid, _, _, err := Validate(writer, utils.GlobalFlags.PersistentFlags, utils.GlobalFlags.ValidateFlags)

// Note: all invalid SBOMs (that fail schema validation) MUST result in an InvalidSBOMError()
if err != nil {
@@ -180,7 +180,7 @@ func normalizeValidationErrorTypes(document *schema.Sbom, valid bool, err error)
getLogger().Info(message)
}

func Validate(persistentFlags utils.PersistentCommandFlags, validateFlags utils.ValidateCommandFlags) (valid bool, document *schema.Sbom, schemaErrors []gojsonschema.ResultError, err error) {
func Validate(output io.Writer, persistentFlags utils.PersistentCommandFlags, validateFlags utils.ValidateCommandFlags) (valid bool, document *schema.Sbom, schemaErrors []gojsonschema.ResultError, err error) {
getLogger().Enter()
defer getLogger().Exit()

@@ -299,7 +299,14 @@ func Validate(persistentFlags utils.PersistentCommandFlags, validateFlags utils.
schemaErrors)

// Format error results and append to InvalidSBOMError error "details"
errInvalid.Details = FormatSchemaErrors(schemaErrors, validateFlags, persistentFlags.OutputFormat)
formattedErrors := FormatSchemaErrors(schemaErrors, validateFlags, persistentFlags.OutputFormat)
errInvalid.Details = formattedErrors

// Always produce JSON output (since it is considered non-informational), ignoring the `--quiet` flags
if persistentFlags.Quiet && persistentFlags.OutputFormat == FORMAT_JSON {
// Note: JSON data files MUST ends in a newline s as this is a POSIX standard
fmt.Fprintf(output, "%s\n", formattedErrors)
}

return INVALID, document, schemaErrors, errInvalid
}
@@ -313,6 +320,8 @@ func Validate(persistentFlags utils.PersistentCommandFlags, validateFlags utils.
}
}

// TODO: Need to perhaps factor in these errors into the JSON output as if they
// were actual schema errors...
// Perform additional validation in document composition/structure
// and "custom" required data within specified fields
if utils.GlobalFlags.ValidateFlags.CustomValidation {
24 changes: 20 additions & 4 deletions cmd/validate_test.go
Original file line number Diff line number Diff line change
@@ -18,9 +18,12 @@
package cmd

import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io/fs"
"os"
"testing"

"github.com/CycloneDX/sbom-utility/schema"
@@ -63,8 +66,8 @@ func innerValidateError(t *testing.T, filename string, variant string, format st

// Invoke the actual validate function
var isValid bool
//isValid, document, schemaErrors, actualError = Validate()
isValid, document, schemaErrors, actualError = Validate(utils.GlobalFlags.PersistentFlags, utils.GlobalFlags.ValidateFlags)

isValid, document, schemaErrors, actualError = Validate(os.Stdout, utils.GlobalFlags.PersistentFlags, utils.GlobalFlags.ValidateFlags)

getLogger().Tracef("document: `%s`, isValid=`%t`, actualError=`%T`", document.GetFilename(), isValid, actualError)

@@ -96,6 +99,19 @@ func innerValidateError(t *testing.T, filename string, variant string, format st
return
}

func innerValidateErrorBuffered(t *testing.T, filename string, variant string, format string, expectedError error) (schemaErrors []gojsonschema.ResultError, outputBuffer bytes.Buffer, err error) {
// Declare an output outputBuffer/outputWriter to use used during tests
var outputWriter = bufio.NewWriter(&outputBuffer)
// ensure all data is written to buffer before further validation
defer outputWriter.Flush()

// Invoke the actual command (API)
isValid, document, schemaErrors, actualError := Validate(outputWriter, utils.GlobalFlags.PersistentFlags, utils.GlobalFlags.ValidateFlags)
getLogger().Tracef("document: `%s`, isValid=`%t`, actualError=`%T`", document.GetFilename(), isValid, actualError)

return
}

// Tests *ErrorInvalidSBOM error types and any (lower-level) errors they "wrapped"
func innerValidateInvalidSBOMInnerError(t *testing.T, filename string, variant string, innerError error) (document *schema.Sbom, schemaErrors []gojsonschema.ResultError, actualError error) {
getLogger().Enter()
@@ -277,7 +293,7 @@ func TestValidateForceCustomSchemaCdxSchemaOlder(t *testing.T) {

func TestValidateCdx14ErrorResultsUniqueComponentsJson(t *testing.T) {
//utils.GlobalFlags.ValidateFlags.ForcedJsonSchemaFile = TEST_SCHEMA_CDX_1_3_CUSTOM
innerValidateError(t,
innerValidateErrorBuffered(t,
TEST_CDX_1_4_VALIDATE_ERR_COMPONENTS_UNIQUE,
SCHEMA_VARIANT_NONE,
FORMAT_JSON,
@@ -286,7 +302,7 @@ func TestValidateCdx14ErrorResultsUniqueComponentsJson(t *testing.T) {

func TestValidateCdx14ErrorResultsFormatIriReferencesJson(t *testing.T) {
//utils.GlobalFlags.ValidateFlags.ForcedJsonSchemaFile = TEST_SCHEMA_CDX_1_3_CUSTOM
innerValidateError(t,
innerValidateErrorBuffered(t,
TEST_CDX_1_4_VALIDATE_ERR_FORMAT_IRI_REFERENCE,
SCHEMA_VARIANT_NONE,
FORMAT_JSON,