-
Notifications
You must be signed in to change notification settings - Fork 39
fix: handle glob patterns when expanded by the shell #583
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
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 |
|---|---|---|
|
|
@@ -35,3 +35,4 @@ dist/ | |
|
|
||
| # Test files | ||
| /tests/fixtures/identifiers | ||
| .DS_Store | ||
This file contains hidden or 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 hidden or 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,194 @@ | ||
| package model | ||
|
|
||
| import ( | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestExpandTestFilePatterns_SingleFile(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| files, err := expandTestFilePatterns([]string{"../../example/model.fga.yaml"}, []string{}) | ||
| require.NoError(t, err) | ||
| assert.Len(t, files, 1) | ||
| assert.Contains(t, files[0], "example/model.fga.yaml") | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_MultipleFilesWithFlag(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| files, err := expandTestFilePatterns( | ||
| []string{"../../example/model.fga.yaml", "../../example/store_abac.fga.yaml"}, | ||
| []string{}, | ||
| ) | ||
| require.NoError(t, err) | ||
| assert.Len(t, files, 2) | ||
| assert.True(t, anyContains(files, "example/model.fga.yaml")) | ||
| assert.True(t, anyContains(files, "example/store_abac.fga.yaml")) | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_GlobPattern(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| files, err := expandTestFilePatterns([]string{"../../example/*.fga.yaml"}, []string{}) | ||
| require.NoError(t, err) | ||
| assert.GreaterOrEqual(t, len(files), 2, "should match at least model.fga.yaml and store_abac.fga.yaml") | ||
| assert.True(t, anyContains(files, "example/model.fga.yaml")) | ||
| assert.True(t, anyContains(files, "example/store_abac.fga.yaml")) | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_ShellExpandedFiles(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| // Simulate what happens when the shell expands: --tests file1 file2 | ||
| // The first file goes to the flag, the second becomes a positional arg | ||
| files, err := expandTestFilePatterns( | ||
| []string{"../../example/model.fga.yaml"}, | ||
| []string{"../../example/store_abac.fga.yaml"}, | ||
| ) | ||
| require.NoError(t, err) | ||
| assert.Len(t, files, 2) | ||
| assert.True(t, anyContains(files, "example/model.fga.yaml")) | ||
| assert.True(t, anyContains(files, "example/store_abac.fga.yaml")) | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_MixedGlobAndLiteral(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| files, err := expandTestFilePatterns( | ||
| []string{"../../example/model.fga.yaml", "../../example/*.fga.yaml"}, | ||
| []string{}, | ||
| ) | ||
| require.NoError(t, err) | ||
| // Should include model.fga.yaml and store_abac.fga.yaml | ||
| assert.GreaterOrEqual(t, len(files), 2, "should have at least 2 files") | ||
| assert.True(t, anyContains(files, "example/model.fga.yaml")) | ||
| assert.True(t, anyContains(files, "example/store_abac.fga.yaml")) | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_SubdirectoryGlob(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| files, err := expandTestFilePatterns([]string{"../../example/subdir/*.fga.yaml"}, []string{}) | ||
| require.NoError(t, err) | ||
| assert.Len(t, files, 1) | ||
| assert.True(t, anyContains(files, "example/subdir/simple.fga.yaml")) | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_NonExistentFile(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| files, err := expandTestFilePatterns([]string{"../../example/nonexistent.fga.yaml"}, []string{}) | ||
| require.Error(t, err) | ||
| assert.Nil(t, files) | ||
| assert.Contains(t, err.Error(), "does not exist", "error should mention file doesn't exist") | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_NoMatchingFiles(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| files, err := expandTestFilePatterns([]string{"../../example/*.nonexistent"}, []string{}) | ||
| require.Error(t, err) | ||
| assert.Nil(t, files) | ||
| assert.Contains(t, err.Error(), "does not exist", "error should mention no files found") | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_NoFilesSpecified(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| files, err := expandTestFilePatterns([]string{}, []string{}) | ||
| require.Error(t, err) | ||
| assert.Nil(t, files) | ||
| assert.Contains(t, err.Error(), "no test files specified") | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_ShellExpandedThreeFiles(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| // Simulate shell expanding multiple globs that result in 3 files | ||
| files, err := expandTestFilePatterns( | ||
| []string{"../../example/model.fga.yaml"}, | ||
| []string{"../../example/store_abac.fga.yaml", "../../example/subdir/simple.fga.yaml"}, | ||
| ) | ||
| require.NoError(t, err) | ||
| assert.Len(t, files, 3) | ||
| assert.True(t, anyContains(files, "example/model.fga.yaml")) | ||
| assert.True(t, anyContains(files, "example/store_abac.fga.yaml")) | ||
| assert.True(t, anyContains(files, "example/subdir/simple.fga.yaml")) | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_GlobPatternNotExpandedByShell(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| // When user quotes the pattern, shell doesn't expand it | ||
| // So the CLI receives the glob pattern itself | ||
| files, err := expandTestFilePatterns([]string{"../../example/*.fga.yaml"}, []string{}) | ||
| require.NoError(t, err) | ||
| assert.GreaterOrEqual(t, len(files), 2, "should expand glob to at least 2 files") | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_CombineGlobAndShellExpanded(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| // Mixed scenario: one file and one glob pattern as positional arg | ||
| files, err := expandTestFilePatterns( | ||
| []string{"../../example/model.fga.yaml"}, | ||
| []string{"../../example/subdir/*.fga.yaml"}, | ||
| ) | ||
| require.NoError(t, err) | ||
| assert.Len(t, files, 2) | ||
| assert.True(t, anyContains(files, "example/model.fga.yaml")) | ||
| assert.True(t, anyContains(files, "example/subdir/simple.fga.yaml")) | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_InvalidGlobPattern(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| // Test with an invalid glob pattern (contains invalid characters for glob) | ||
| files, err := expandTestFilePatterns([]string{"../../example/[.fga.yaml"}, []string{}) | ||
| require.Error(t, err) | ||
| assert.Nil(t, files) | ||
| assert.Contains(t, err.Error(), "invalid tests pattern") | ||
| } | ||
|
|
||
| func TestExpandTestFilePatterns_Deduplication(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| // Test that duplicate files from overlapping patterns are deduplicated | ||
| files, err := expandTestFilePatterns( | ||
| []string{ | ||
| "../../example/model.fga.yaml", | ||
| "../../example/*.fga.yaml", // This will also match model.fga.yaml | ||
| "../../example/model.fga.yaml", | ||
| }, | ||
| []string{}, | ||
| ) | ||
| require.NoError(t, err) | ||
| // Should have at least 2 files (model.fga.yaml and store_abac.fga.yaml) | ||
| assert.GreaterOrEqual(t, len(files), 2) | ||
|
|
||
| // Count occurrences of model.fga.yaml - should only appear once | ||
| count := 0 | ||
|
|
||
| for _, file := range files { | ||
| if strings.Contains(file, "example/model.fga.yaml") { | ||
| count++ | ||
| } | ||
| } | ||
|
|
||
| assert.Equal(t, 1, count, "model.fga.yaml should only appear once despite being matched multiple times") | ||
| } | ||
|
|
||
| // anyContains checks if any string in the slice contains the given substring. | ||
| func anyContains(slice []string, substr string) bool { | ||
| for _, s := range slice { | ||
| if strings.Contains(s, substr) { | ||
| return true | ||
| } | ||
| } | ||
|
|
||
| return false | ||
| } |
This file contains hidden or 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,23 @@ | ||
| name: Simple Test Store | ||
| model: | | ||
| model | ||
| schema 1.1 | ||
|
|
||
| type user | ||
|
|
||
| type document | ||
| relations | ||
| define reader: [user] | ||
|
|
||
| tuples: | ||
| - user: user:alice | ||
| relation: reader | ||
| object: document:readme | ||
|
|
||
| tests: | ||
| - name: "simple-test" | ||
| check: | ||
| - user: user:alice | ||
| object: document:readme | ||
| assertions: | ||
| reader: true |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.