Clone

 view release on metacpan or  search on metacpan

t/14-weakened-ref.t  view on Meta::CPAN

#!/usr/bin/perl
use strict;
use warnings;

use Test::More;
use Clone qw(clone);

BEGIN {
    eval 'use Scalar::Util qw( weaken isweak );';
    if ($@) {
        plan skip_all => "Scalar::Util::weaken not available";
        exit;
    }
}

plan tests => 16;

# GH #15 - Weakened refs always clone as undef
# When cloning a structure with weakened references, Clone should
# preserve the weakness and keep referents alive when strong
# references to them exist elsewhere in the clone graph.

{
    package Parent;
    sub new { bless { children => [] }, shift }

    package Child;
    sub new {
        my ($class, $parent) = @_;
        my $child = bless { parent => $parent }, $class;
        Scalar::Util::weaken($child->{parent});
        push @{ $parent->{children} }, $child;
        return $child;
    }
}

# Test 1: Clone from parent side (strong ref to child, weak ref back)
# This is the primary fix: when the referent has strong references
# elsewhere in the clone graph, the weakened ref should survive.
{
    my $p = Parent->new();
    my $c = Child->new($p);

    my $p_clone = clone($p);

    ok(defined $p_clone->{children}[0]{parent},
       'weakened ref survives when cloning from parent side');
    isnt($p_clone, $p, 'cloned parent is a different object');
    is($p_clone->{children}[0]{parent}, $p_clone,
       'cloned child points to cloned parent (not original)');
    ok(Scalar::Util::isweak($p_clone->{children}[0]{parent}),
       'weakened ref is still weak after cloning parent');
}

# Test 2: Multiple children with weakened refs to same parent
{
    my $p = Parent->new();
    my $c1 = Child->new($p);
    my $c2 = Child->new($p);

    my $p_clone = clone($p);

    ok(defined $p_clone->{children}[0]{parent},
       'first child weakened ref survives');
    ok(defined $p_clone->{children}[1]{parent},
       'second child weakened ref survives');
    is($p_clone->{children}[0]{parent}, $p_clone->{children}[1]{parent},
       'both children point to same cloned parent');
    ok(Scalar::Util::isweak($p_clone->{children}[0]{parent}),
       'first child ref is weak');
    ok(Scalar::Util::isweak($p_clone->{children}[1]{parent}),
       'second child ref is weak');
}

# Test 3: Hash with both strong and weak ref to same target
{
    my $data = { value => 42 };
    my $holder = { strong => $data, weak => $data };
    weaken($holder->{weak});



( run in 1.296 second using v1.01-cache-2.11-cpan-7f9471e7e0a )