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

feat: Add JUnit output format for test results #1508

Merged
merged 5 commits into from
Apr 5, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions api/genpb/cerbos/policy/v1/hashpb_helpers.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

144 changes: 77 additions & 67 deletions api/genpb/cerbos/policy/v1/policy.pb.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions api/genpb/cerbos/policy/v1/policy.pb.validate.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 43 additions & 0 deletions api/genpb/cerbos/policy/v1/policy_vtproto.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions api/genpb/cerbos/private/v1/hashpb_helpers.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions api/genpb/cerbos/response/v1/hashpb_helpers.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions api/public/cerbos/policy/v1/policy.proto
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ message TestResults {
Summary summary = 4;
string error = 5;
repeated TestCase test_cases = 6;
string description = 7;
}

message TestCase {
Expand Down
48 changes: 33 additions & 15 deletions cmd/cerbos/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@
"os"
"os/signal"

"github.com/cerbos/cerbos/cmd/cerbos/compile/internal/verification"

Check failure on line 14 in cmd/cerbos/compile/compile.go

View workflow job for this annotation

GitHub Actions / Test (3)

other declaration of verification

Check failure on line 14 in cmd/cerbos/compile/compile.go

View workflow job for this annotation

GitHub Actions / Test (3)

other declaration of verification

"github.com/cerbos/cerbos/cmd/cerbos/compile/internal/verification"

Check failure on line 16 in cmd/cerbos/compile/compile.go

View workflow job for this annotation

GitHub Actions / Test (3)

verification redeclared in this block

Check failure on line 16 in cmd/cerbos/compile/compile.go

View workflow job for this annotation

GitHub Actions / Test (3)

"github.com/cerbos/cerbos/cmd/cerbos/compile/internal/verification" imported and not used

Check failure on line 16 in cmd/cerbos/compile/compile.go

View workflow job for this annotation

GitHub Actions / Test (3)

verification redeclared in this block

Check failure on line 16 in cmd/cerbos/compile/compile.go

View workflow job for this annotation

GitHub Actions / Test (3)

"github.com/cerbos/cerbos/cmd/cerbos/compile/internal/verification" imported and not used
oguzhand95 marked this conversation as resolved.
Show resolved Hide resolved

"github.com/alecthomas/kong"
"github.com/fatih/color"
"github.com/pterm/pterm"
"go.uber.org/zap"

policyv1 "github.com/cerbos/cerbos/api/genpb/cerbos/policy/v1"
compileerrors "github.com/cerbos/cerbos/cmd/cerbos/compile/errors"
internalcompile "github.com/cerbos/cerbos/cmd/cerbos/compile/internal/compilation"
internalerrors "github.com/cerbos/cerbos/cmd/cerbos/compile/internal/errors"
"github.com/cerbos/cerbos/cmd/cerbos/compile/internal/flagset"
"github.com/cerbos/cerbos/cmd/cerbos/compile/internal/lint"
"github.com/cerbos/cerbos/cmd/cerbos/compile/internal/verification"
"github.com/cerbos/cerbos/internal/compile"
"github.com/cerbos/cerbos/internal/engine"
"github.com/cerbos/cerbos/internal/outputcolor"
Expand All @@ -33,7 +36,8 @@
"github.com/cerbos/cerbos/internal/verify"
)

const help = `
const (
help = `
Examples:

# Compile and run tests found in /path/to/policy/repo
Expand All @@ -48,17 +52,19 @@

cerbos compile --skip-tests /path/to/policy/repo
`
)

type Cmd struct { //nolint:govet // Kong prints fields in order, so we don't want to reorder fields to save bytes.
Dir string `help:"Policy directory" arg:"" required:"" type:"existingdir"`
IgnoreSchemas bool `help:"Ignore schemas during compilation"`
Tests string `help:"Path to the directory containing tests. Defaults to policy directory." type:"existingdir"`
RunRegex string `help:"Run only tests that match this regex" name:"run"`
SkipTests bool `help:"Skip tests"`
Output flagset.OutputFormat `help:"Output format (${enum})" default:"tree" enum:"tree,list,json" short:"o"`
Color *outputcolor.Level `help:"Output color level (auto,never,always,256,16m). Defaults to auto." xor:"color"`
NoColor bool `help:"Disable colored output" xor:"color"`
Verbose bool `help:"Verbose output on test failure"`
Dir string `help:"Policy directory" arg:"" required:"" type:"existingdir"`
IgnoreSchemas bool `help:"Ignore schemas during compilation"`
Tests string `help:"Path to the directory containing tests. Defaults to policy directory." type:"existingdir"`
RunRegex string `help:"Run only tests that match this regex" name:"run"`
SkipTests bool `help:"Skip tests"`
Output flagset.OutputFormat `help:"Output format (${enum})" default:"tree" enum:"tree,list,json" short:"o"`
TestOutput *flagset.VerificationOutputFormat `help:"Test output format. If unspecified matches the value of the output flag. (tree,list,json,junit)"`
Color *outputcolor.Level `help:"Output color level (auto,never,always,256,16m). Defaults to auto." xor:"color"`
NoColor bool `help:"Disable colored output" xor:"color"`
Verbose bool `help:"Verbose output on test failure"`
}

func (c *Cmd) Run(k *kong.Kong) error {
Expand Down Expand Up @@ -109,6 +115,19 @@
return fmt.Errorf("failed to create engine: %w", err)
}

if c.TestOutput == nil {
var value flagset.VerificationOutputFormat
switch c.Output {
case flagset.OutputFormatTree:
value = flagset.VerificationOutputFormatTree
case flagset.OutputFormatList:
value = flagset.VerificationOutputFormatList
case flagset.OutputFormatJSON:
value = flagset.VerificationOutputFormatJSON
}
c.TestOutput = &value
}

if !c.SkipTests {
verifyConf := verify.Config{
Run: c.RunRegex,
Expand All @@ -130,14 +149,13 @@
return fmt.Errorf("failed to run tests: %w", err)
}

err = verification.Display(p, results, c.Output, c.Verbose, colorLevel)
if err != nil {
if err = verification.Display(p, results, *c.TestOutput, c.Verbose, colorLevel); err != nil {
return fmt.Errorf("failed to display test results: %w", err)
}

switch results.Summary.OverallResult {
case policyv1.TestResults_RESULT_FAILED, policyv1.TestResults_RESULT_ERRORED:
return internalerrors.ErrTestsFailed
return compileerrors.ErrTestsFailed
default:
}
}
Expand Down
8 changes: 4 additions & 4 deletions cmd/cerbos/compile/internal/compilation/display.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
package compilation

import (
internalerrors "github.com/cerbos/cerbos/cmd/cerbos/compile/internal/errors"
compileerrors "github.com/cerbos/cerbos/cmd/cerbos/compile/errors"
"github.com/cerbos/cerbos/cmd/cerbos/compile/internal/flagset"
"github.com/cerbos/cerbos/internal/compile"
"github.com/cerbos/cerbos/internal/outputcolor"
Expand All @@ -20,15 +20,15 @@ func Display(p *printer.Printer, errs compile.ErrorList, output flagset.OutputFo
return displayList(p, errs)
}

return internalerrors.ErrFailed
return compileerrors.ErrFailed
}

func displayJSON(p *printer.Printer, errs compile.ErrorList, colorLevel outputcolor.Level) error {
if err := p.PrintJSON(map[string]compile.ErrorList{"compileErrors": errs}, colorLevel); err != nil {
return err
}

return internalerrors.ErrFailed
return compileerrors.ErrFailed
}

func displayList(p *printer.Printer, errs compile.ErrorList) error {
Expand All @@ -37,5 +37,5 @@ func displayList(p *printer.Printer, errs compile.ErrorList) error {
p.Printf("%s: %s (%s)\n", colored.FileName(err.File), colored.ErrorMsg(err.Description), err.Error)
}

return internalerrors.ErrFailed
return compileerrors.ErrFailed
}
19 changes: 19 additions & 0 deletions cmd/cerbos/compile/internal/flagset/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,29 @@

package flagset

import "fmt"

type OutputFormat string

const (
OutputFormatTree OutputFormat = "tree"
OutputFormatList OutputFormat = "list"
OutputFormatJSON OutputFormat = "json"
)

type VerificationOutputFormat string

func (v *VerificationOutputFormat) Validate() error {
if !(*v == "tree" || *v == "list" || *v == "json" || *v == "junit") {
return fmt.Errorf("available options are tree, list, json or junit")
oguzhand95 marked this conversation as resolved.
Show resolved Hide resolved
}

return nil
}

const (
VerificationOutputFormatTree VerificationOutputFormat = "tree"
VerificationOutputFormatList VerificationOutputFormat = "list"
VerificationOutputFormatJSON VerificationOutputFormat = "json"
VerificationOutputFormatJUnit VerificationOutputFormat = "junit"
)
8 changes: 4 additions & 4 deletions cmd/cerbos/compile/internal/lint/display.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
package lint

import (
internalerrors "github.com/cerbos/cerbos/cmd/cerbos/compile/internal/errors"
compileerrors "github.com/cerbos/cerbos/cmd/cerbos/compile/errors"
"github.com/cerbos/cerbos/cmd/cerbos/compile/internal/flagset"
"github.com/cerbos/cerbos/internal/outputcolor"
"github.com/cerbos/cerbos/internal/printer"
Expand All @@ -20,15 +20,15 @@ func Display(p *printer.Printer, errs *index.BuildError, output flagset.OutputFo
return displayList(p, errs)
}

return internalerrors.ErrFailed
return compileerrors.ErrFailed
}

func displayJSON(p *printer.Printer, errs *index.BuildError, colorLevel outputcolor.Level) error {
if err := p.PrintJSON(map[string]*index.BuildError{"lintErrors": errs}, colorLevel); err != nil {
return err
}

return internalerrors.ErrFailed
return compileerrors.ErrFailed
}

func displayList(p *printer.Printer, errs *index.BuildError) error {
Expand Down Expand Up @@ -72,5 +72,5 @@ func displayList(p *printer.Printer, errs *index.BuildError) error {
p.Println()
}

return internalerrors.ErrFailed
return compileerrors.ErrFailed
}
28 changes: 24 additions & 4 deletions cmd/cerbos/compile/internal/verification/display.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
package verification

import (
"encoding/xml"
"fmt"
"strings"

"github.com/pterm/pterm"
"github.com/pterm/pterm/putils"
Expand All @@ -15,6 +17,7 @@ import (
"github.com/cerbos/cerbos/internal/outputcolor"
"github.com/cerbos/cerbos/internal/printer"
"github.com/cerbos/cerbos/internal/printer/colored"
"github.com/cerbos/cerbos/internal/verify/junit"
)

const (
Expand Down Expand Up @@ -44,19 +47,36 @@ var (
}
)

func Display(p *printer.Printer, results *policyv1.TestResults, output flagset.OutputFormat, verbose bool, colorLevel outputcolor.Level) error {
func Display(p *printer.Printer, results *policyv1.TestResults, output flagset.VerificationOutputFormat, verbose bool, colorLevel outputcolor.Level) error {
switch output {
case flagset.OutputFormatJSON:
case flagset.VerificationOutputFormatJSON:
return p.PrintProtoJSON(results, colorLevel)
case flagset.OutputFormatTree:
case flagset.VerificationOutputFormatTree:
return displayTree(p, pterm.DefaultTree, results, verbose)
case flagset.OutputFormatList:
case flagset.VerificationOutputFormatList:
return displayTree(p, pterm.TreePrinter{Indent: listIndent, VerticalString: " "}, results, verbose)
case flagset.VerificationOutputFormatJUnit:
return displayJUnit(p, results, verbose)
default:
return nil
}
}

func displayJUnit(p *printer.Printer, results *policyv1.TestResults, verbose bool) error {
r, err := junit.Build(results, verbose)
if err != nil {
return fmt.Errorf("failed to build JUnit XML: %w", err)
}

output, err := xml.MarshalIndent(r, "", strings.Repeat(" ", listIndent))
if err != nil {
return fmt.Errorf("failed to marshal xml: %w", err)
}

p.Println(string(output))
return nil
}

func displayTree(p *printer.Printer, tp pterm.TreePrinter, results *policyv1.TestResults, verbose bool) error {
output := buildTestOutput(results, verbose)

Expand Down