From 1135deec9e0b397adc7ee60ab09559e6a698c7dc Mon Sep 17 00:00:00 2001 From: jmontesi Date: Sun, 3 Dec 2023 08:32:58 +0100 Subject: [PATCH 1/2] cli: display information about the CNFCERT run There are four sections displayed: 1) Basic information about the CNFCERT version and artifacts 2) Live results for the tests that are running 3) Table that summarizes the result of each test suite 4) Log output for those tests that failed --- internal/cli/cli.go | 49 ++++++++++++++++++++++++++++++++ main.go | 28 +++++++++++++++---- pkg/checksdb/check.go | 24 ++++++++++++++++ pkg/checksdb/checksdb.go | 56 +++++++++++++++++++++++++++++++++++++ pkg/checksdb/checksgroup.go | 4 +++ pkg/configuration/utils.go | 3 +- pkg/versions/versions.go | 2 +- run-cnf-suites.sh | 10 +++---- 8 files changed, 163 insertions(+), 13 deletions(-) create mode 100644 internal/cli/cli.go diff --git a/internal/cli/cli.go b/internal/cli/cli.go new file mode 100644 index 000000000..d1054bb34 --- /dev/null +++ b/internal/cli/cli.go @@ -0,0 +1,49 @@ +package cli + +import ( + "fmt" +) + +const ( + Reset = "\033[0m" + Red = "\033[31m" + Green = "\033[32m" + Yellow = "\033[33m" + Blue = "\033[34m" + Purple = "\033[35m" + Cyan = "\033[36m" + Gray = "\033[37m" + White = "\033[97m" +) + +const banner = ` + + _____ _ _ ______ _____ _____ ______ _____ __ _____ _____ __ +/ __ \| \ | || ___|/ __ \| ___|| ___ \|_ _| / / | ___| | _ |\ \ +| / \/| \| || |_ | / \/| |__ | |_/ / | | | | __ __|___ \ | |/' | | | +| | | . || _| | | | __| | / | | | | \ \ / / \ \ | /| | | | +| \__/\| |\ || | | \__/\| |___ | |\ \ | | | | \ V / /\__/ / _ \ |_/ / | | + \____/\_| \_/\_| \____/\____/ \_| \_| \_/ | | \_/ \____/ (_) \___/ | | + \_\ /_/ + + +` + +func PrintBanner() { + fmt.Print(banner) +} + +func PrintResultsTable(results map[string][]int) { + fmt.Printf("\n") + fmt.Println("-----------------------------------------------------------") + fmt.Printf("| %-27s %-9s %-9s %s |\n", "SUITE", "PASSED", "FAILED", "SKIPPED") + fmt.Println("-----------------------------------------------------------") + for groupName, groupResults := range results { + fmt.Printf("| %-25s %8d %9d %10d |\n", groupName, + groupResults[0], + groupResults[1], + groupResults[2]) + fmt.Println("-----------------------------------------------------------") + } + fmt.Printf("\n") +} diff --git a/main.go b/main.go index 45806be72..5a050c4d6 100644 --- a/main.go +++ b/main.go @@ -31,6 +31,7 @@ import ( "github.com/test-network-function/cnf-certification-test/cnf-certification-test/webserver" + "github.com/test-network-function/cnf-certification-test/internal/cli" "github.com/test-network-function/cnf-certification-test/internal/clientsholder" "github.com/test-network-function/cnf-certification-test/internal/log" "github.com/test-network-function/cnf-certification-test/pkg/configuration" @@ -106,7 +107,6 @@ func setLogLevel() { logLevel = logrus.DebugLevel } - logrus.Info("Log level set to: ", logLevel) logrus.SetLevel(logLevel) } @@ -144,14 +144,23 @@ func main() { loghelper.SetLogFormat() setLogLevel() + logrusLogFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE, logFilePermissions) + if err != nil { + fmt.Fprintf(os.Stderr, "could not create log file, err: %v", err) + os.Exit(1) + } + defer logrusLogFile.Close() + + logrus.SetOutput(logrusLogFile) + // Set up logger - err = os.Remove(logFileName) + err = os.Remove("test_log") // TODO: use proper file when logrus is removed if err != nil && !os.IsNotExist(err) { fmt.Fprintf(os.Stderr, "could not delete old log file, err: %v", err) - os.Exit(1) + os.Exit(1) //nolint:gocritic // the error will not happen after logrus is removed } - logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE, logFilePermissions) + logFile, err := os.OpenFile("test_log", os.O_RDWR|os.O_CREATE, logFilePermissions) if err != nil { fmt.Fprintf(os.Stderr, "could not create log file, err: %v", err) os.Exit(1) @@ -165,6 +174,15 @@ func main() { logrus.Infof("Claim Format Version: %s", versions.ClaimFormatVersion) logrus.Infof("Labels filter : %v", *labelsFlag) + cli.PrintBanner() + + fmt.Printf("CNFCERT version: %s\n", versions.GitVersion()) + fmt.Printf("Claim file version: %s\n", versions.ClaimFormatVersion) + fmt.Printf("Checks filter: %s\n", *labelsFlag) + fmt.Printf("Output folder: %s\n", *claimPath) + fmt.Printf("Log file: %s\n", logFileName) + fmt.Printf("\n") + _ = clientsholder.GetClientsHolder(getK8sClientsConfigFileNames()...) certsuite.LoadChecksDB(*labelsFlag) @@ -172,7 +190,7 @@ func main() { if *listFlag { // ToDo: List all the available checks, filtered with --labels. logrus.Errorf("Not implemented yet.") - os.Exit(1) //nolint:gocritic + os.Exit(1) } // Diagnostic functions will run when no labels are provided. diff --git a/pkg/checksdb/check.go b/pkg/checksdb/check.go index 1fa97af2b..cec57aeff 100644 --- a/pkg/checksdb/check.go +++ b/pkg/checksdb/check.go @@ -8,6 +8,7 @@ import ( "time" "github.com/sirupsen/logrus" + "github.com/test-network-function/cnf-certification-test/internal/cli" "github.com/test-network-function/cnf-certification-test/internal/log" "github.com/test-network-function/cnf-certification-test/pkg/testhelper" ) @@ -18,6 +19,10 @@ const ( CheckResultFailed = "failed" CheckResultError = "error" CheckResultAborted = "aborted" + + CheckResultTagPass = "PASS" + CheckResultTagSkip = "SKIP" + CheckResultTagFail = "FAIL" ) type skipMode int @@ -246,6 +251,8 @@ func (check *Check) Run() error { return fmt.Errorf("unable to run due to a previously existing error: %v", check.Error) } + fmt.Printf("[ "+cli.Cyan+"RUNNING"+cli.Reset+" ] %s", check.ID) + check.StartTime = time.Now() defer func() { check.EndTime = time.Now() @@ -268,5 +275,22 @@ func (check *Check) Run() error { } } + printCheckResult(check) + return nil } + +const nbCharsToAvoidLineAliasing = 20 + +//nolint:goconst +func printCheckResult(check *Check) { + checkID := check.ID + strings.Repeat(" ", nbCharsToAvoidLineAliasing) + switch check.Result { + case CheckResultPassed: + fmt.Printf("\r[ "+cli.Green+"%s"+cli.Reset+" ] %s\n", CheckResultTagPass, checkID) + case CheckResultFailed: + fmt.Printf("\r[ "+cli.Red+"%s"+cli.Reset+" ] %s\n", CheckResultTagFail, checkID) + case CheckResultSkipped: + fmt.Printf("\r[ "+cli.Yellow+"%s"+cli.Reset+" ] %s\n", CheckResultTagSkip, checkID) + } +} diff --git a/pkg/checksdb/checksdb.go b/pkg/checksdb/checksdb.go index df02b7b29..fb33c58f4 100644 --- a/pkg/checksdb/checksdb.go +++ b/pkg/checksdb/checksdb.go @@ -4,12 +4,15 @@ import ( "fmt" "os" "os/signal" + "strings" "sync" "syscall" "time" + "unicode/utf8" "github.com/sirupsen/logrus" "github.com/test-network-function/cnf-certification-test/cnf-certification-test/identifiers" + "github.com/test-network-function/cnf-certification-test/internal/cli" "github.com/test-network-function/test-network-function-claim/pkg/claim" ) @@ -25,6 +28,7 @@ func AddCheck(check *Check) { db = append(db, check) } +//nolint:funlen func RunChecks(labelsExpr string, timeout time.Duration) error { dbLock.Lock() defer dbLock.Unlock() @@ -79,6 +83,10 @@ func RunChecks(labelsExpr string, timeout time.Duration) error { group.RecordChecksResults() } + // Print the results in the CLI + cli.PrintResultsTable(getResultsSummary()) + printFailedChecksLog() + if len(errs) > 0 { logrus.Errorf("RunChecks errors: %v", errs) return fmt.Errorf("%d errors found in checks/groups", len(errs)) @@ -132,3 +140,51 @@ func GetReconciledResults() map[string]interface{} { } return resultMap } + +const ( + PASSED = 0 + FAILED = 1 + SKIPPED = 2 +) + +func getResultsSummary() map[string][]int { + results := make(map[string][]int) + for groupName, group := range dbByGroup { + groupResults := []int{0, 0, 0} + for _, check := range group.checks { + switch check.Result { + case CheckResultPassed: + groupResults[PASSED]++ + case CheckResultFailed: + groupResults[FAILED]++ + case CheckResultSkipped: + groupResults[SKIPPED]++ + } + } + results[groupName] = groupResults + } + return results +} + +const nbColorSymbols = 9 + +func printFailedChecksLog() { + for _, group := range dbByGroup { + for _, check := range group.checks { + if check.Result != CheckResultFailed { + continue + } + logHeader := fmt.Sprintf("| "+cli.Cyan+"LOG (%s)"+cli.Reset+" |", check.ID) + nbSymbols := utf8.RuneCountInString(logHeader) - nbColorSymbols + fmt.Println(strings.Repeat("-", nbSymbols)) + fmt.Println(logHeader) + fmt.Println(strings.Repeat("-", nbSymbols)) + log := check.GetLogs() + if log == "" { + fmt.Println("Empty log output") + } else { + fmt.Println(log) + } + } + } +} diff --git a/pkg/checksdb/checksgroup.go b/pkg/checksdb/checksgroup.go index 08f1a7f04..6f3a857eb 100644 --- a/pkg/checksdb/checksgroup.go +++ b/pkg/checksdb/checksgroup.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/sirupsen/logrus" + "github.com/test-network-function/cnf-certification-test/internal/cli" ) type ChecksGroup struct { @@ -76,6 +77,8 @@ func (group *ChecksGroup) Add(check *Check) { func skipCheck(check *Check, reason string) { logrus.Infof("Skipping check %s, reason: %s", check.ID, reason) + fmt.Printf("[ "+cli.Yellow+"SKIP"+cli.Reset+" ] %s\n", check.ID) + check.SetResultSkipped(reason) } @@ -284,6 +287,7 @@ func runCheck(check *Check, group *ChecksGroup, remainingChecks []*Check) (err e //nolint:funlen func (group *ChecksGroup) RunChecks(labelsExpr string, stopChan <-chan bool) (errs []error) { logrus.Infof("Running group %q checks.", group.name) + fmt.Printf("Running suite %s\n", strings.ToUpper(group.name)) labelsExprEvaluator, err := NewLabelsExprEvaluator(labelsExpr) if err != nil { diff --git a/pkg/configuration/utils.go b/pkg/configuration/utils.go index f5a738e9e..f149a54b6 100644 --- a/pkg/configuration/utils.go +++ b/pkg/configuration/utils.go @@ -63,12 +63,11 @@ func LoadConfiguration(filePath string) (TestConfiguration, error) { } func LoadEnvironmentVariables() error { - log.Info("Saving environment variables & parameters.") err := envconfig.Process("tnf", ¶meters) if err != nil { return fmt.Errorf("could not process the environment variables values, error: %v", err) } - log.Infof("Environment: %+v", parameters) + return nil } diff --git a/pkg/versions/versions.go b/pkg/versions/versions.go index 5ac8cf234..297f0a365 100644 --- a/pkg/versions/versions.go +++ b/pkg/versions/versions.go @@ -26,5 +26,5 @@ func GitVersion() string { GitDisplayRelease = GitRelease } - return GitDisplayRelease + " ( " + GitCommit + " )" + return GitDisplayRelease + " (" + GitCommit + ")" } diff --git a/run-cnf-suites.sh b/run-cnf-suites.sh index d8fb27cda..4445ff0ad 100755 --- a/run-cnf-suites.sh +++ b/run-cnf-suites.sh @@ -2,7 +2,7 @@ # [debug] uncomment line below to print out the statements as they are being # executed. -set -x +# set -x # defaults export OUTPUT_LOC="$PWD/cnf-certification-test" @@ -94,14 +94,14 @@ if [ "$SERVER_RUN" = "true" ]; then EXTRA_ARGS="$EXTRA_ARGS -serverMode" fi -echo "Label: $LABEL" +# echo "Label: $LABEL" if [[ $LABEL == "all" ]]; then LABEL='common,extended,faredge,telco' fi -echo "Running with label filter '$LABEL'" -echo "Report will be output to '$OUTPUT_LOC'" -echo "Extra arguments '${EXTRA_ARGS}'" +# echo "Running with label filter '$LABEL'" +# echo "Report will be output to '$OUTPUT_LOC'" +# echo "Extra arguments '${EXTRA_ARGS}'" LABEL_STRING='' if [ -z "$LABEL" ] && { [ -z "$SERVER_RUN" ] || [ "$SERVER_RUN" == "false" ]; }; then From f121ec57e2664e231338932c1110f0086e9687d1 Mon Sep 17 00:00:00 2001 From: jmontesi Date: Tue, 5 Dec 2023 10:19:32 +0100 Subject: [PATCH 2/2] Add banner font source --- internal/cli/cli.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/cli/cli.go b/internal/cli/cli.go index d1054bb34..08ead8ba1 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -16,6 +16,9 @@ const ( White = "\033[97m" ) +// ASCII art generated on http://www.patorjk.com/software/taag/ with +// the font DOOM by Frans P. de Vries 18 Jun 1996. +// All backticks (`) were removed for string literal compatibility. const banner = ` _____ _ _ ______ _____ _____ ______ _____ __ _____ _____ __