diff options
Diffstat (limited to 'internal/apply/swap_test.go')
| -rw-r--r-- | internal/apply/swap_test.go | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/internal/apply/swap_test.go b/internal/apply/swap_test.go index 297db72..dd7cc07 100644 --- a/internal/apply/swap_test.go +++ b/internal/apply/swap_test.go @@ -303,3 +303,66 @@ func TestDisplaceThatCannotBeReportedFailsTheStep(t *testing.T) { t.Error("the copy ran even though the displace could not be logged") } } + +// TestSymlinkInsideTheSortedDirectoryStopsTheStep: placeholders are already +// stopped from redirecting a step out of the directory a rule named. A +// symlink is a name too: one planted in the sorted directory - by an +// unpacked archive, say - named after a rule's destination sends the file +// anywhere, while the plan the user approved shows only "Out/". +func TestSymlinkInsideTheSortedDirectoryStopsTheStep(t *testing.T) { + root := t.TempDir() + outside := t.TempDir() + if err := os.Symlink(outside, filepath.Join(root, "Out")); err != nil { + t.Skipf("symlinks unavailable: %v", err) + } + src := filepath.Join(root, "a.pdf") + dst := filepath.Join(root, "Out", "a.pdf") + c := planned(t, root, "a.pdf", "body", plan.Step{Kind: plan.Move, Src: src, Dst: dst}) + c.Root = root + + res, err := ChainLogged(context.Background(), c, nil, nil) + if err != nil { + t.Fatal(err) + } + if res[0].Status != "failed" || !strings.Contains(res[0].Detail, "symlink") { + t.Errorf("step = %+v; want a failure naming the symlink", res[0]) + } + if _, err := os.Lstat(filepath.Join(outside, "a.pdf")); err == nil { + t.Error("the file left the sorted directory through the symlink") + } + if _, err := os.Lstat(src); err != nil { + t.Errorf("the file is no longer where it started: %v", err) + } +} + +// TestASymlinkedDestinationOutsideTheSortedDirectoryIsFine: a destination +// the configuration itself names - "~/docs/work", where ~/docs is a symlink +// to another disk - is the user's own arrangement, not something planted, +// and must keep working. +func TestASymlinkedDestinationOutsideTheSortedDirectoryIsFine(t *testing.T) { + root := t.TempDir() + elsewhere := t.TempDir() + real := filepath.Join(elsewhere, "real") + if err := os.MkdirAll(real, 0o755); err != nil { + t.Fatal(err) + } + link := filepath.Join(elsewhere, "docs") + if err := os.Symlink(real, link); err != nil { + t.Skipf("symlinks unavailable: %v", err) + } + src := filepath.Join(root, "a.pdf") + dst := filepath.Join(link, "a.pdf") + c := planned(t, root, "a.pdf", "body", plan.Step{Kind: plan.Move, Src: src, Dst: dst}) + c.Root = root + + res, err := ChainLogged(context.Background(), c, nil, nil) + if err != nil { + t.Fatal(err) + } + if res[0].Status != "ok" { + t.Fatalf("step = %+v; want it to go through", res[0]) + } + if _, err := os.Lstat(filepath.Join(real, "a.pdf")); err != nil { + t.Errorf("the file did not reach the configured destination: %v", err) + } +} |
