Filter and account final glob candidates
This commit is contained in:
203
internal/engine/glob_selection_test.go
Normal file
203
internal/engine/glob_selection_test.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
)
|
||||
|
||||
func TestSelectGlobFiltersOnlyWildcardDiscoveredEntries(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
root := t.TempDir()
|
||||
for name, content := range map[string]string{
|
||||
".hidden/secret.yaml": "value: hidden\n",
|
||||
"visible/item.yaml": "value: visible\n",
|
||||
"visible/source.txt": "value: source\n",
|
||||
} {
|
||||
filename := filepath.Join(root, filepath.FromSlash(name))
|
||||
if err := os.MkdirAll(filepath.Dir(filename), 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filename, []byte(content), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for alias, target := range map[string]string{
|
||||
"visible-alias": "visible",
|
||||
"selected.yaml": "visible/source.txt",
|
||||
"unselected.txt": "visible/item.yaml",
|
||||
".secret.yaml": "visible/source.txt",
|
||||
} {
|
||||
if err := os.Symlink(target, filepath.Join(root, filepath.FromSlash(alias))); err != nil {
|
||||
t.Skipf("symlinks are unavailable: %v", err)
|
||||
}
|
||||
}
|
||||
access, err := openHostAccess(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer access.close()
|
||||
|
||||
selection := selectGlobForTest(t, access, root, ` - glob: '*/*.yaml'
|
||||
follow: false
|
||||
hidden: false
|
||||
`)
|
||||
if got, want := selectedPathsRelativeTo(selection, root), []string{"visible/item.yaml"}; !equalStrings(got, want) {
|
||||
t.Fatalf("filtered glob candidates = %#v, want %#v", got, want)
|
||||
}
|
||||
|
||||
selection = selectGlobForTest(t, access, root, ` - glob: '.hidden/*.yaml'
|
||||
follow: false
|
||||
hidden: false
|
||||
`)
|
||||
if got, want := selectedPathsRelativeTo(selection, root), []string{".hidden/secret.yaml"}; !equalStrings(got, want) {
|
||||
t.Fatalf("literal hidden component candidates = %#v, want %#v", got, want)
|
||||
}
|
||||
|
||||
selection = selectGlobForTest(t, access, root, ` - glob: 'visible-alias/*.yaml'
|
||||
follow: false
|
||||
hidden: false
|
||||
`)
|
||||
if got, want := selectedPathsRelativeTo(selection, root), []string{"visible-alias/item.yaml"}; !equalStrings(got, want) {
|
||||
t.Fatalf("literal symlink component candidates = %#v, want %#v", got, want)
|
||||
}
|
||||
|
||||
selection = selectGlobForTest(t, access, root, ` - glob: '*.yaml'
|
||||
follow: false
|
||||
hidden: true
|
||||
`)
|
||||
if len(selection.candidates) != 0 {
|
||||
t.Fatalf("follow:false selected a discovered file symlink: %#v", selection.candidates)
|
||||
}
|
||||
|
||||
selection = selectGlobForTest(t, access, root, ` - glob: '*.yaml'
|
||||
follow: true
|
||||
hidden: false
|
||||
`)
|
||||
if got, want := selectedPathsRelativeTo(selection, root), []string{"selected.yaml"}; !equalStrings(got, want) {
|
||||
t.Fatalf("filename aliases were not filtered by candidate spelling: %#v, want %#v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectGlobAppliesExclusionsBeforeSourceAdmissionWithoutOpeningFiles(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
filesystem := &observedGlobFilesystem{files: fstest.MapFS{
|
||||
"parts": &fstest.MapFile{Mode: fs.ModeDir | 0o700},
|
||||
"parts/keep.yaml": &fstest.MapFile{Data: []byte("not parsed: [\n")},
|
||||
"parts/skip-one.yaml": &fstest.MapFile{Data: []byte("not parsed: [\n")},
|
||||
"parts/skip-two.yaml": &fstest.MapFile{Data: []byte("not parsed: [\n")},
|
||||
"parts/skip-three.yaml": &fstest.MapFile{Data: []byte("not parsed: [\n")},
|
||||
}}
|
||||
access := newNativeAccess(filesystem, ".", &namespaceToken{})
|
||||
specs, diagnostics := parseImportSpecsYAML(t, ` - glob: 'parts/*.yaml'
|
||||
exclude: 'skip-*.yaml'
|
||||
`)
|
||||
if len(diagnostics) != 0 {
|
||||
t.Fatal(diagnostics)
|
||||
}
|
||||
policy, diagnostics := resolveImportPolicy(specs[0], importDefaults{})
|
||||
if len(diagnostics) != 0 {
|
||||
t.Fatal(diagnostics)
|
||||
}
|
||||
limits := defaultImportLimits()
|
||||
limits.sources = 2
|
||||
accounting := &importAccounting{sources: 1}
|
||||
selection, diagnostics := selectGlobImportCandidates(access, ".", specs[0], policy, limits, accounting)
|
||||
if len(diagnostics) != 0 || !equalStrings(selectedPaths(selection), []string{"parts/keep.yaml"}) {
|
||||
t.Fatalf("post-exclusion selection, diagnostics = %#v, %#v", selection, diagnostics)
|
||||
}
|
||||
if len(filesystem.opened) != 1 || filesystem.opened[0] != "parts" {
|
||||
t.Fatalf("glob opened paths = %#v, want only the parts directory", filesystem.opened)
|
||||
}
|
||||
if accounting.sources+len(selection.candidates) > limits.sources {
|
||||
t.Fatalf("final candidate set exceeds the private source limit: accounting=%#v selection=%#v", accounting, selection.candidates)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectGlobRejectsEscapingWildcardLinks(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
root := t.TempDir()
|
||||
outside := t.TempDir()
|
||||
if err := os.WriteFile(filepath.Join(outside, "file.yaml"), []byte("value: outside\n"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Symlink(outside, filepath.Join(root, "escape")); err != nil {
|
||||
t.Skipf("symlinks are unavailable: %v", err)
|
||||
}
|
||||
access, err := openHostAccess(root)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer access.close()
|
||||
|
||||
_, diagnostics := selectGlobForTestWithDiagnostics(t, access, root, ` - glob: '*/file.yaml'
|
||||
follow: true
|
||||
`)
|
||||
if len(diagnostics) != 1 || diagnostics[0].Code != CodeImportOutsideRoot {
|
||||
t.Fatalf("escaping glob diagnostics = %#v, want import.outside_root", diagnostics)
|
||||
}
|
||||
selection := selectGlobForTest(t, access, root, ` - glob: '*/file.yaml'
|
||||
follow: false
|
||||
`)
|
||||
if len(selection.candidates) != 0 {
|
||||
t.Fatalf("follow:false selected an escaping alias: %#v", selection.candidates)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectGlobPreservesMatchedDirectoryValidityBeforeExclusion(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
filesystem := fstest.MapFS{
|
||||
"parts": &fstest.MapFile{Mode: fs.ModeDir | 0o700},
|
||||
"parts/matched.yaml": &fstest.MapFile{Mode: fs.ModeDir | 0o700},
|
||||
"parts/matched.yaml/x": &fstest.MapFile{Data: []byte("value: x\n")},
|
||||
}
|
||||
access := newNativeAccess(filesystem, ".", &namespaceToken{})
|
||||
_, diagnostics := selectGlobForTestWithDiagnostics(t, access, ".", ` - glob: 'parts/*.yaml'
|
||||
exclude: '*.yaml'
|
||||
`)
|
||||
if len(diagnostics) != 1 || diagnostics[0].Code != CodeSourceNotRegular {
|
||||
t.Fatalf("excluded directory diagnostics = %#v, want source.not_regular", diagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
func selectGlobForTest(t *testing.T, access *filesystemAccess, base, declaration string) importSelection {
|
||||
t.Helper()
|
||||
selection, diagnostics := selectGlobForTestWithDiagnostics(t, access, base, declaration)
|
||||
if len(diagnostics) != 0 {
|
||||
t.Fatalf("glob selection diagnostics = %#v", diagnostics)
|
||||
}
|
||||
return selection
|
||||
}
|
||||
|
||||
func selectGlobForTestWithDiagnostics(t *testing.T, access *filesystemAccess, base, declaration string) (importSelection, []Diagnostic) {
|
||||
t.Helper()
|
||||
specs, diagnostics := parseImportSpecsYAML(t, declaration)
|
||||
if len(diagnostics) != 0 {
|
||||
t.Fatalf("parse diagnostics = %#v", diagnostics)
|
||||
}
|
||||
policy, diagnostics := resolveImportPolicy(specs[0], importDefaults{})
|
||||
if len(diagnostics) != 0 {
|
||||
t.Fatalf("policy diagnostics = %#v", diagnostics)
|
||||
}
|
||||
return selectGlobImportCandidates(access, base, specs[0], policy, defaultImportLimits(), &importAccounting{})
|
||||
}
|
||||
|
||||
type observedGlobFilesystem struct {
|
||||
files fstest.MapFS
|
||||
opened []string
|
||||
}
|
||||
|
||||
func (filesystem *observedGlobFilesystem) Open(name string) (fs.File, error) {
|
||||
filesystem.opened = append(filesystem.opened, name)
|
||||
return filesystem.files.Open(name)
|
||||
}
|
||||
|
||||
func (filesystem *observedGlobFilesystem) Stat(name string) (fs.FileInfo, error) {
|
||||
return fs.Stat(filesystem.files, name)
|
||||
}
|
||||
Reference in New Issue
Block a user