Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* read test files Signed-off-by: Will Beason <willbeason@google.com> * Make gator root command Per decision in weekly meeting, make the "gator" root command and "test" the subcommand in charge of running the tests. This frees us up to add other subcommands that we want to do later. Signed-off-by: Will Beason <willbeason@google.com> Co-authored-by: Sertaç Özercan <852750+sozercan@users.noreply.github.com>
- Loading branch information
Showing
8 changed files
with
199 additions
and
96 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/open-policy-agent/gatekeeper/cmd/gator/test" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
const version = "alpha" | ||
|
||
func init() { | ||
rootCmd.AddCommand(test.Cmd) | ||
} | ||
|
||
var rootCmd = &cobra.Command{ | ||
Use: "gator subcommand", | ||
Short: "gator is a suite of authorship tools for Gatekeeper", | ||
Version: version, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return nil | ||
}, | ||
} | ||
|
||
func main() { | ||
err := rootCmd.Execute() | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package test | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"io/fs" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/open-policy-agent/gatekeeper/pkg/gktest" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
const ( | ||
examples = ` # Run all tests in label-tests.yaml | ||
gator test label-tests.yaml | ||
# Run all suites whose names contain "forbid-labels". | ||
gator test tests/... --run forbid-labels// | ||
# Run all tests whose names contain "nginx-deployment". | ||
gator test tests/... --run //nginx-deployment | ||
# Run all tests whose names exactly match "nginx-deployment". | ||
gator test tests/... --run '//^nginx-deployment$' | ||
# Run all tests that are either named "forbid-labels" or are | ||
# in suites named "forbid-labels". | ||
gator test tests/... --run '^forbid-labels$'` | ||
) | ||
|
||
var run string | ||
|
||
func init() { | ||
Cmd.Flags().StringVarP(&run, "run", "r", "", | ||
`regular expression which filters tests to run by name`) | ||
} | ||
|
||
// Cmd is the gator test subcommand. | ||
var Cmd = &cobra.Command{ | ||
Use: "test path [--run=name]", | ||
Short: "test runs suites of tests on Gatekeeper Constraints", | ||
Example: examples, | ||
Args: cobra.ExactArgs(1), | ||
RunE: runE, | ||
} | ||
|
||
func runE(_ *cobra.Command, args []string) error { | ||
path := args[0] | ||
|
||
// Convert path to be absolute. Allowing for relative and absolute paths | ||
// everywhere in the code leads to unnecessary complexity, so the first | ||
// thing we do on encountering a path is to convert it to an absolute path. | ||
var err error | ||
if !filepath.IsAbs(path) { | ||
path, err = filepath.Abs(path) | ||
if err != nil { | ||
return fmt.Errorf("getting absolute path: %w", err) | ||
} | ||
} | ||
|
||
// Create the base file system. We use fs.FS rather than direct calls to | ||
// os.ReadFile or filepath.WalkDir to make testing easier and keep logic | ||
// os-independent. | ||
fileSystem := getFS(path) | ||
|
||
suites, err := gktest.ReadSuites(fileSystem, path) | ||
if err != nil { | ||
return fmt.Errorf("listing test files: %w", err) | ||
} | ||
filter, err := gktest.NewFilter(run) | ||
if err != nil { | ||
return fmt.Errorf("compiling filter: %w", err) | ||
} | ||
|
||
return runSuites(fileSystem, suites, filter) | ||
} | ||
|
||
func runSuites(fileSystem fs.FS, suites []gktest.Suite, filter gktest.Filter) error { | ||
isFailure := false | ||
for _, s := range suites { | ||
if !filter.MatchesSuite(s) { | ||
continue | ||
} | ||
|
||
results := s.Run(fileSystem, filter) | ||
for _, result := range results { | ||
if result.IsFailure() { | ||
isFailure = true | ||
} | ||
fmt.Println(result.String()) | ||
} | ||
} | ||
|
||
if isFailure { | ||
// At least one test failed or there was a problem executing tests in at | ||
// least one file. | ||
return errors.New("FAIL") | ||
} | ||
return nil | ||
} | ||
|
||
func getFS(path string) fs.FS { | ||
// TODO(#1397): Check that this produces the correct file system string on | ||
// Windows. We may need to add a trailing `/` for fs.FS to function properly. | ||
root := filepath.VolumeName(path) | ||
if root == "" { | ||
// We are running on a unix-like filesystem without volume names, so the | ||
// file system root is `/`. | ||
root = "/" | ||
} | ||
|
||
return os.DirFS(root) | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package gktest | ||
|
||
import "io/fs" | ||
|
||
// ReadSuites returns the set of test Suites selected by path. | ||
// | ||
// 1) If path is a path to a Suite, parses and returns the Suite. | ||
// 2) If the path is a directory, returns the Suites defined in that directory | ||
// (not recursively). | ||
// 3) If the path is a directory followed by "...", returns all Suites in that | ||
// directory and its subdirectories. | ||
// | ||
// Returns an error if: | ||
// - path is a file that does not define a Suite | ||
// - any matched files containing Suites are not parseable | ||
func ReadSuites(f fs.FS, path string) ([]Suite, error) { | ||
return nil, nil | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package gktest | ||
|
||
import "io/fs" | ||
|
||
// Suite defines a set of TestCases which all use the same ConstraintTemplate | ||
// and Constraint. | ||
type Suite struct { | ||
TestCases []TestCase | ||
} | ||
|
||
// Run executes every TestCase in the Suite. Returns the results for every | ||
// TestCase. | ||
func (s Suite) Run(f fs.FS, filter Filter) []Result { | ||
results := make([]Result, len(s.TestCases)) | ||
for i, tc := range s.TestCases { | ||
if !filter.MatchesTest(tc) { | ||
continue | ||
} | ||
|
||
results[i] = tc.Run(f) | ||
} | ||
return results | ||
} | ||
|
||
// TestCase runs Constraint against a YAML object | ||
type TestCase struct{} | ||
|
||
// Run executes the TestCase and returns the Result of the run. | ||
func (tc TestCase) Run(f fs.FS) Result { | ||
return Result{} | ||
} |