Skip to content

bug: directory rename leaks child mocks — missing weaken on re-keyed entries #416

Description

@toddr-bot

When __rename re-keys directory children in %files_being_mocked, the new hash entries are stored as strong references. Every other insertion point (new(), _new_link_for_broken_symlink(), _maybe_autovivify()) immediately weakens the entry via Scalar::Util::weaken(), but __rename omits this step.

Impact

After renaming a directory, child mock objects cannot be garbage collected. When the user's variable goes out of scope, the mock persists in %files_being_mocked and continues intercepting file operations on those paths.

Reproduction

use Test::MockFile qw(nostrict);
use Scalar::Util qw(isweak);

my $dir   = Test::MockFile->new_dir("/tmp/testdir");
my $child = Test::MockFile->file("/tmp/testdir/child.txt", "hello");
my $dest  = Test::MockFile->dir("/tmp/newdir");

rename("/tmp/testdir", "/tmp/newdir") or die;

# Entry should be weak but isn't:
say isweak($Test::MockFile::files_being_mocked{"/tmp/newdir/child.txt"});  # prints nothing (false)

# Mock leaks — persists after user drops reference:
undef $child;
say defined $Test::MockFile::files_being_mocked{"/tmp/newdir/child.txt"};  # prints 1 (should be false)

Fix

Add Scalar::Util::weaken( $files_being_mocked{$new_key} ) after the re-keying assignment in __rename.


🤖 Created by Kōan from autonomous session

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions