package engine import ( "io/fs" "os" "path/filepath" "strings" "testing" "testing/fstest" ) func TestSelectShallowDirectoriesUnionsRootsAndPatterns(t *testing.T) { t.Parallel() filesystem := fstest.MapFS{ "one": &fstest.MapFile{Mode: fs.ModeDir | 0o700}, "one/a.yaml": &fstest.MapFile{Data: []byte("a: 1\n")}, "one/README": &fstest.MapFile{Data: []byte("readme\n")}, "one/.hidden": &fstest.MapFile{Data: []byte("hidden\n")}, "one/draft.draft.yaml": &fstest.MapFile{Data: []byte("draft\n")}, "one/nested/deep.yaml": &fstest.MapFile{Data: []byte("deep: 1\n")}, "two": &fstest.MapFile{Mode: fs.ModeDir | 0o700}, "two/a.yaml": &fstest.MapFile{Data: []byte("a: 2\n")}, "three": &fstest.MapFile{Mode: fs.ModeDir | 0o700}, "three/extensionless": &fstest.MapFile{Data: []byte("plain\n")}, } access := newNativeAccess(filesystem, ".", &namespaceToken{}) specs, diagnostics := parseImportSpecsYAML(t, ` - dir: [one, one, missing, two] pattern: ['*.yaml', 'a.*', 'README'] exclude: '*.draft.yaml' required: true `) if len(diagnostics) != 0 { t.Fatal(diagnostics) } policy, diagnostics := resolveImportPolicy(specs[0], importDefaults{}) if len(diagnostics) != 0 { t.Fatal(diagnostics) } accounting := &importAccounting{} selection, diagnostics := selectDirectoryImportCandidates(access, ".", specs[0], policy, defaultImportLimits(), accounting) if len(diagnostics) != 0 { t.Fatalf("selection diagnostics = %#v", diagnostics) } if len(selection.candidates) != 3 { t.Fatalf("selection = %#v, want three unioned matches", selection) } if selection.candidates[0].path != "one/README" || selection.candidates[1].path != "one/a.yaml" || selection.candidates[2].path != "two/a.yaml" { t.Fatalf("selected paths = %#v", selection.candidates) } if accounting.entries != 6 { t.Fatalf("entry visits = %d, want 6 entries across distinct roots", accounting.entries) } } func TestSelectShallowDirectoriesIncludeUnrestrictedHiddenAndExtensionlessFiles(t *testing.T) { t.Parallel() root := t.TempDir() for name, value := range map[string]string{ "a.yaml": "a: 1\n", ".private": "private\n", "README": "readme\n", "nested/deep": "deep\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(value), 0o600); err != nil { t.Fatal(err) } } access, err := openHostAccess(root) if err != nil { t.Fatal(err) } defer access.close() specs, diagnostics := parseImportSpecsYAML(t, " - dir: .\n") if len(diagnostics) != 0 { t.Fatal(diagnostics) } policy, diagnostics := resolveImportPolicy(specs[0], importDefaults{}) if len(diagnostics) != 0 { t.Fatal(diagnostics) } selection, diagnostics := selectDirectoryImportCandidates(access, root, specs[0], policy, defaultImportLimits(), &importAccounting{}) if len(diagnostics) != 0 { t.Fatalf("selection diagnostics = %#v", diagnostics) } if len(selection.candidates) != 3 { t.Fatalf("selected files = %#v, want yaml, hidden, and extensionless files", selection.candidates) } for _, candidate := range selection.candidates { if filepath.Base(candidate.path) == "deep" { t.Fatalf("shallow search descended into a child directory: %#v", selection.candidates) } } } func TestSelectShallowDirectoriesApplyRequirednessToFinalUnion(t *testing.T) { t.Parallel() filesystem := fstest.MapFS{ "available": &fstest.MapFile{Mode: fs.ModeDir | 0o700}, "available/match.yaml": &fstest.MapFile{Data: []byte("match: true\n")}, "available/excluded.yaml": &fstest.MapFile{Data: []byte("excluded: true\n")}, } access := newNativeAccess(filesystem, ".", &namespaceToken{}) for _, test := range []struct { name string yaml string wantError bool wantCount int }{ { name: "missing root alongside a match", yaml: " - dir: [missing, available]\n pattern: '*.yaml'\n exclude: excluded.yaml\n required: true\n", wantCount: 1, }, { name: "all matches excluded", yaml: " - dir: available\n pattern: '*.yaml'\n exclude: '*.yaml'\n required: true\n", wantError: true, }, { name: "explicit empty patterns select nothing", yaml: " - dir: available\n pattern: []\n", wantCount: 0, }, { name: "empty search roots", yaml: " - dir: []\n required: true\n", wantError: true, }, } { t.Run(test.name, func(t *testing.T) { specs, diagnostics := parseImportSpecsYAML(t, test.yaml) if len(diagnostics) != 0 { t.Fatal(diagnostics) } policy, diagnostics := resolveImportPolicy(specs[0], importDefaults{}) if len(diagnostics) != 0 { t.Fatal(diagnostics) } selection, diagnostics := selectDirectoryImportCandidates(access, ".", specs[0], policy, defaultImportLimits(), &importAccounting{}) if test.wantError { if len(diagnostics) != 1 || diagnostics[0].Code != CodeImportMissing { t.Fatalf("diagnostics = %#v, want required empty-union error", diagnostics) } return } if len(diagnostics) != 0 || len(selection.candidates) != test.wantCount { t.Fatalf("selection, diagnostics = %#v, %#v", selection, diagnostics) } if test.wantCount == 1 && selection.candidates[0].path != "available/match.yaml" { t.Fatalf("selected path = %q, want available/match.yaml", selection.candidates[0].path) } }) } } func TestSelectShallowDirectoryRejectsInvalidRootInsteadOfTreatingItAsMissing(t *testing.T) { t.Parallel() filesystem := fstest.MapFS{ "file.yaml": &fstest.MapFile{Data: []byte("not a directory\n")}, } access := newNativeAccess(filesystem, ".", &namespaceToken{}) specs, diagnostics := parseImportSpecsYAML(t, " - dir: file.yaml\n") if len(diagnostics) != 0 { t.Fatal(diagnostics) } policy, diagnostics := resolveImportPolicy(specs[0], importDefaults{}) if len(diagnostics) != 0 { t.Fatal(diagnostics) } _, diagnostics = selectDirectoryImportCandidates(access, ".", specs[0], policy, defaultImportLimits(), &importAccounting{}) if len(diagnostics) != 1 || diagnostics[0].Code != CodeImportInvalid { t.Fatalf("invalid-root diagnostics = %#v", diagnostics) } denied := &statOnlyImportFilesystem{statErrors: map[string]error{"denied": fs.ErrPermission}} access = newNativeAccess(denied, ".", &namespaceToken{}) specs, diagnostics = parseImportSpecsYAML(t, " - dir: denied\n") if len(diagnostics) != 0 { t.Fatal(diagnostics) } policy, diagnostics = resolveImportPolicy(specs[0], importDefaults{}) if len(diagnostics) != 0 { t.Fatal(diagnostics) } _, diagnostics = selectDirectoryImportCandidates(access, ".", specs[0], policy, defaultImportLimits(), &importAccounting{}) if len(diagnostics) != 1 || diagnostics[0].Code != CodeImportInvalid { t.Fatalf("inaccessible-root diagnostics = %#v", diagnostics) } } func TestSelectShallowDirectoryFiltersSymlinkAliasSpelling(t *testing.T) { t.Parallel() root := t.TempDir() if err := os.WriteFile(filepath.Join(root, "welcome.yaml"), []byte("welcome: true\n"), 0o600); err != nil { t.Fatal(err) } if err := os.Symlink("welcome.yaml", filepath.Join(root, "welcome.draft.yaml")); err != nil { t.Skipf("symlinks are unavailable: %v", err) } access, err := openHostAccess(root) if err != nil { t.Fatal(err) } defer access.close() specs, diagnostics := parseImportSpecsYAML(t, " - dir: .\n pattern: '*.yaml'\n exclude: '*.draft.yaml'\n") if len(diagnostics) != 0 { t.Fatal(diagnostics) } policy, diagnostics := resolveImportPolicy(specs[0], importDefaults{}) if len(diagnostics) != 0 { t.Fatal(diagnostics) } selection, diagnostics := selectDirectoryImportCandidates(access, root, specs[0], policy, defaultImportLimits(), &importAccounting{}) if len(diagnostics) != 0 || len(selection.candidates) != 1 || filepath.Base(selection.candidates[0].path) != "welcome.yaml" { t.Fatalf("alias filtering selection, diagnostics = %#v, %#v", selection, diagnostics) } } func TestSelectDirectoriesApplyRecursiveDepthToFileLevels(t *testing.T) { t.Parallel() root := t.TempDir() for name := range map[string]struct{}{ "direct.yaml": {}, "child/child.yaml": {}, "child/grand/grand.yaml": {}, } { 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("value: true\n"), 0o600); err != nil { t.Fatal(err) } } access, err := openHostAccess(root) if err != nil { t.Fatal(err) } defer access.close() for _, test := range []struct { name string yaml string defaults importDefaults wantPaths []string }{ { name: "depth one includes direct files", yaml: " - dir: .\n recursive: true\n depth: 1\n pattern: '*.yaml'\n", wantPaths: []string{"direct.yaml"}, }, { name: "depth two includes one descendant level", yaml: " - dir: .\n recursive: true\n depth: 2\n pattern: '*.yaml'\n", wantPaths: []string{"child.yaml", "direct.yaml"}, }, { name: "zero depth is unlimited", yaml: " - dir: .\n recursive: true\n depth: 0\n pattern: '*.yaml'\n", wantPaths: []string{"child.yaml", "grand.yaml", "direct.yaml"}, }, { name: "recursion stays disabled by default", yaml: " - dir: .\n pattern: '*.yaml'\n", wantPaths: []string{"direct.yaml"}, }, { name: "explicit false overrides application recursion", yaml: " - dir: .\n recursive: false\n pattern: '*.yaml'\n", defaults: importDefaults{recursive: boolPointer(true)}, wantPaths: []string{"direct.yaml"}, }, { name: "application default enables recursion for depth", yaml: " - dir: .\n depth: 2\n pattern: '*.yaml'\n", defaults: importDefaults{recursive: boolPointer(true)}, wantPaths: []string{"child.yaml", "direct.yaml"}, }, { name: "large depth remains a valid unlimited traversal bound", yaml: " - dir: .\n recursive: true\n depth: 999999999999999999999999999999\n pattern: '*.yaml'\n", wantPaths: []string{"child.yaml", "grand.yaml", "direct.yaml"}, }, { name: "filename filter does not prune directories", yaml: " - dir: .\n recursive: true\n depth: 3\n pattern: grand.yaml\n", wantPaths: []string{"grand.yaml"}, }, } { t.Run(test.name, func(t *testing.T) { specs, diagnostics := parseImportSpecsYAML(t, test.yaml) if len(diagnostics) != 0 { t.Fatal(diagnostics) } policy, diagnostics := resolveImportPolicy(specs[0], test.defaults) if len(diagnostics) != 0 { t.Fatal(diagnostics) } selection, diagnostics := selectDirectoryImportCandidates(access, root, specs[0], policy, defaultImportLimits(), &importAccounting{}) if len(diagnostics) != 0 { t.Fatalf("selection diagnostics = %#v", diagnostics) } var got []string for _, candidate := range selection.candidates { got = append(got, filepath.Base(candidate.path)) } if strings.Join(got, ",") != strings.Join(test.wantPaths, ",") { t.Fatalf("selected basenames = %#v, want %#v", got, test.wantPaths) } }) } } func TestSelectDirectoriesRetainsEmptySearchAndDirectoryVisitLimits(t *testing.T) { t.Parallel() root := t.TempDir() for _, name := range []string{"direct.yaml", "child/child.yaml", "child/grand/grand.yaml"} { 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("value: true\n"), 0o600); err != nil { t.Fatal(err) } } access, err := openHostAccess(root) if err != nil { t.Fatal(err) } defer access.close() specs, diagnostics := parseImportSpecsYAML(t, " - dir: .\n recursive: true\n pattern: []\n") if len(diagnostics) != 0 { t.Fatal(diagnostics) } policy, diagnostics := resolveImportPolicy(specs[0], importDefaults{}) if len(diagnostics) != 0 { t.Fatal(diagnostics) } accounting := &importAccounting{} selection, diagnostics := selectDirectoryImportCandidates(access, root, specs[0], policy, defaultImportLimits(), accounting) if len(diagnostics) != 0 || len(selection.candidates) != 0 { t.Fatalf("empty recursive selection, diagnostics = %#v, %#v", selection, diagnostics) } if accounting.entries != 5 { t.Fatalf("empty search visited %d entries, want all 5 within the recursive search", accounting.entries) } limited := defaultImportLimits() limited.entries = 2 _, diagnostics = selectDirectoryImportCandidates(access, root, specs[0], policy, limited, &importAccounting{}) if len(diagnostics) != 1 || diagnostics[0].Code != CodeImportLimitExceeded { t.Fatalf("directory limit diagnostics = %#v", diagnostics) } } func boolPointer(value bool) *bool { return &value }