Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 27 additions & 0 deletions acceptance.bats
Original file line number Diff line number Diff line change
Expand Up @@ -530,3 +530,30 @@ EOF"
[ "$status" -eq 1 ]
[[ "$output" =~ "10 tests, 3 passed, 0 warnings, 7 failures, 0 exceptions" ]]
}

@test "File name override flag replaces stdin filename in output" {
run bash -c "./conftest test --file-name-override='my-custom-file.yaml' -p examples/kubernetes/policy - < examples/kubernetes/service.yaml"
[ "$status" -eq 0 ]
[[ "$output" =~ "my-custom-file.yaml" ]]
[[ ! "$output" =~ "-" ]]
}

@test "File name override flag does not affect regular files" {
run ./conftest test --file-name-override='override.yaml' -p examples/kubernetes/policy examples/kubernetes/service.yaml
[ "$status" -eq 0 ]
[[ "$output" =~ "examples/kubernetes/service.yaml" ]]
[[ ! "$output" =~ "override.yaml" ]]
}

@test "File name override flag works with JSON output" {
run bash -c "./conftest test --file-name-override='custom.json' --output json -p examples/kubernetes/policy - < examples/kubernetes/service.yaml"
[ "$status" -eq 0 ]
[[ "$output" =~ "\"filename\":\"custom.json\"" ]]
[[ ! "$output" =~ "\"filename\":\"-\"" ]]
}

@test "Without file name override flag, stdin shows as dash" {
run bash -c "./conftest test -p examples/kubernetes/policy - < examples/kubernetes/service.yaml"
[ "$status" -eq 0 ]
[[ "$output" =~ "-" ]]
}
2 changes: 2 additions & 0 deletions internal/commands/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func NewTestCommand(ctx context.Context) *cobra.Command {
"junit-hide-message",
"quiet",
"tls",
"file-name-override",
}
for _, name := range flagNames {
if err := viper.BindPFlag(name, cmd.Flags().Lookup(name)); err != nil {
Expand Down Expand Up @@ -196,6 +197,7 @@ func NewTestCommand(ctx context.Context) *cobra.Command {

cmd.Flags().StringSlice("proto-file-dirs", []string{}, "A list of directories containing Protocol Buffer definitions")
cmd.Flags().Bool("tls", true, "Use TLS to access the registry")
cmd.Flags().String("file-name-override", "", "Override the file name for stdin input (used for output formatting)")

return &cmd
}
10 changes: 10 additions & 0 deletions runner/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type TestRunner struct {
Combine bool
Quiet bool
Output string
FileNameOverride string `mapstructure:"file-name-override"`
}

// Run executes the TestRunner, verifying all Rego policies against the given
Expand Down Expand Up @@ -110,6 +111,15 @@ func (t *TestRunner) Run(ctx context.Context, fileList []string) (output.CheckRe
}
}

// Override file name for stdin input if --file-name-override flag is provided
if t.FileNameOverride != "" {
for i := range results {
if results[i].FileName == "-" {
results[i].FileName = t.FileNameOverride
}
}
}

return results, nil
}

Expand Down
158 changes: 158 additions & 0 deletions runner/test_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package runner
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests aren't actually testing the real code. You aren't using the methods on the TestRunner struct. Please add tests using the TestRunner, and add acceptance tests in acceptance.bats.


import (
"context"
"os"
"path/filepath"
"testing"
)

func TestTestRunner_FileNameOverrideFlag(t *testing.T) {
// Create a temporary directory for test files
tmpDir := t.TempDir()

// Create a test policy file
policyDir := filepath.Join(tmpDir, "policy")
if err := os.Mkdir(policyDir, 0755); err != nil {
t.Fatalf("Failed to create policy directory: %v", err)
}

policyContent := `package main

deny contains msg if {
input.kind == "Deployment"
input.metadata.name == "test"
msg := "test deployment found"
}
`
policyFile := filepath.Join(policyDir, "test.rego")
if err := os.WriteFile(policyFile, []byte(policyContent), 0644); err != nil {
t.Fatalf("Failed to write policy file: %v", err)
}

// Test cases
tests := []struct {
name string
fileNameOverride string
expectedFileName string
}{
{
name: "with file-name-override",
fileNameOverride: "my-custom-file.yaml",
expectedFileName: "my-custom-file.yaml",
},
{
name: "without file-name-override",
fileNameOverride: "",
expectedFileName: "-",
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// Create TestRunner with FileNameOverride set
runner := TestRunner{
Policy: []string{policyDir},
Namespace: []string{"main"},
FileNameOverride: tc.fileNameOverride,
RegoVersion: "v1",
}

// Create stdin input by using "-" as the file path
fileList := []string{"-"}

// Mock stdin with test data
oldStdin := os.Stdin
r, w, _ := os.Pipe()
os.Stdin = r
testInput := `{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "test"
}
}`
go func() {
defer w.Close()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This defer isn't needed, you can w.Close() after the line below.

w.Write([]byte(testInput))
}()
defer func() { os.Stdin = oldStdin }()

// Run the test
ctx := context.Background()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer t.Context() in tests.

results, err := runner.Run(ctx, fileList)
if err != nil {
t.Fatalf("Run failed: %v", err)
}

// Verify results
if len(results) == 0 {
t.Fatal("Expected at least one result")
}

// Check that the filename was properly overridden
if results[0].FileName != tc.expectedFileName {
t.Errorf("Expected filename to be '%s', got '%s'", tc.expectedFileName, results[0].FileName)
}
})
}
}

func TestTestRunner_FileNameOverrideOnlyAffectsStdin(t *testing.T) {
// Create a temporary directory for test files
tmpDir := t.TempDir()

// Create a test policy file
policyDir := filepath.Join(tmpDir, "policy")
if err := os.Mkdir(policyDir, 0755); err != nil {
t.Fatalf("Failed to create policy directory: %v", err)
}

policyContent := `package main

deny contains msg if {
input.kind == "Deployment"
msg := "deployment found"
}
`
policyFile := filepath.Join(policyDir, "test.rego")
if err := os.WriteFile(policyFile, []byte(policyContent), 0644); err != nil {
t.Fatalf("Failed to write policy file: %v", err)
}

// Create a test config file
configContent := `apiVersion: apps/v1
kind: Deployment
metadata:
name: test-file
`
configFile := filepath.Join(tmpDir, "deployment.yaml")
if err := os.WriteFile(configFile, []byte(configContent), 0644); err != nil {
t.Fatalf("Failed to write config file: %v", err)
}

// Create TestRunner with FileNameOverride set
runner := TestRunner{
Policy: []string{policyDir},
Namespace: []string{"main"},
FileNameOverride: "overridden-name.yaml",
RegoVersion: "v1",
}

// Run with a regular file (not stdin)
ctx := context.Background()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer t.Context() in tests.

results, err := runner.Run(ctx, []string{configFile})
if err != nil {
t.Fatalf("Run failed: %v", err)
}

// Verify results
if len(results) == 0 {
t.Fatal("Expected at least one result")
}

// Check that the regular file name was NOT overridden
if results[0].FileName != configFile {
t.Errorf("Expected filename to remain '%s', got '%s'", configFile, results[0].FileName)
}
}