diff options
Diffstat (limited to 'internal/plan/hostile_test.go')
| -rw-r--r-- | internal/plan/hostile_test.go | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/internal/plan/hostile_test.go b/internal/plan/hostile_test.go index c22fb24..a2f2bfe 100644 --- a/internal/plan/hostile_test.go +++ b/internal/plan/hostile_test.go @@ -39,7 +39,7 @@ func TestBuildRefusesDotDotFromPlaceholder(t *testing.T) { }} return Build("/r", in, time.Now(), NoDisk{}, NewClaims())[0].Steps[0] } - if s := step("/w/{1}/in"); s.Skip != `destination "/w/../in" leaves its directory through a placeholder` { + if s := step("/w/{1}/in"); s.Skip != `destination "/w/../in" leaves /w through a placeholder` { t.Errorf("placeholder ..: Skip = %q, Dst = %q", s.Skip, s.Dst) } if s := step("/w/../in"); s.Skip != "" || s.Dst != "/in/x.pdf" { @@ -49,3 +49,39 @@ func TestBuildRefusesDotDotFromPlaceholder(t *testing.T) { t.Errorf("..x: Skip = %q, Dst = %q", s.Skip, s.Dst) } } + +// TestBuildKeepsPlaceholdersInsideTheirDirectory: a capture of "~", an +// empty capture, or an extension-less {ext} at the start of a destination +// used to make it $HOME or absolute (review M1). The resolved destination +// must stay under the directory the rule's text names before its first +// placeholder; a destination with no placeholder is the rule's own +// business. +func TestBuildKeepsPlaceholdersInsideTheirDirectory(t *testing.T) { + t.Setenv("HOME", "/home/x") + step := func(name, dest string, caps ...string) Step { + in := []Input{{File: file("/r", name), Rules: []RuleMatch{{Name: "a", Captures: caps, Actions: []config.Action{act(config.Move, dest)}}}}} + return Build("/r", in, time.Now(), NoDisk{}, NewClaims())[0].Steps[0] + } + for _, tc := range []struct { + name, dest string + caps []string + skip bool + dst string + }{ + {"~_i.pdf", "{1}/Filed", []string{"~_", "~"}, true, ""}, + {"_i.pdf", "{1}/Filed", []string{"_", ""}, true, ""}, + {"README", "{ext}/tmp", nil, true, ""}, + {"a.pdf", "Out/{1}", []string{"a", "~"}, false, "/r/Out/~/a.pdf"}, + {"a.pdf", "~/docs/{1}", []string{"a", "x"}, false, "/home/x/docs/x/a.pdf"}, + {"a.pdf", "~/docs/{1}", []string{"a", ".."}, true, ""}, + {"a.pdf", "Work/Ac{1}", []string{"a", "me"}, false, "/r/Work/Acme/a.pdf"}, + {"a.pdf", "/w/{1}/in", []string{"a", ".."}, true, ""}, + {"a.pdf", "/w/../in", nil, false, "/in/a.pdf"}, + {"a.pdf", "{mtime:%Y}", nil, false, "/r/2026/a.pdf"}, + } { + s := step(tc.name, tc.dest, tc.caps...) + if tc.skip != (s.Skip != "") || (!tc.skip && s.Dst != tc.dst) { + t.Errorf("%s -> %s %q: Skip %q Dst %q; want skip=%v dst=%q", tc.name, tc.dest, tc.caps, s.Skip, s.Dst, tc.skip, tc.dst) + } + } +} |
