Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ memory_cycle_ok $reference;

Checks that `$reference` doesn't have any circular memory references.

## no\_memory\_cycle

```
is(
$got,
hash {
no_memory_cycle;
}
);
```

Used in the context of a [Test2::Tools::Compare](https://metacpan.org/pod/Test2::Tools::Compare) comparison. The whole test will fail with
appropriate diagnostics if there is a memory cycle in `$got`.

# CAVEATS

This module is based on and quite similar to [Test::Memory::Cycle](https://metacpan.org/pod/Test::Memory::Cycle). That module is
Expand Down
68 changes: 59 additions & 9 deletions lib/Test2/Tools/MemoryCycle.pm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use experimental qw( signatures );
use Devel::Cycle qw( find_cycle );
use Test2::API qw( context );
use Exporter qw( import );
use Carp qw( croak );

# ABSTRACT: Check for memory leaks and circular memory references
# VERSION
Expand Down Expand Up @@ -53,19 +54,13 @@ Checks that C<$reference> doesn't have any circular memory references.

=cut

our @EXPORT = qw( memory_cycle_ok );

# Adapted from Test::Memory::Cycle for Test2::API
sub memory_cycle_ok ($ref, $msg=undef) {

$msg ||= 'no memory cycle';
our @EXPORT = qw( memory_cycle_ok no_memory_cycle );

sub _find_cycle ($ref) {
my $cycle_no = 0;
my @diags;

# Callback function that is called once for each memory cycle found.
my $callback = sub {
my $path = shift;
my $callback = sub ($path) {
$cycle_no++;
push( @diags, "Cycle #$cycle_no" );
foreach (@$path) {
Expand All @@ -85,6 +80,17 @@ sub memory_cycle_ok ($ref, $msg=undef) {
};

find_cycle( $ref, $callback );

return ($cycle_no, @diags);
}

# Adapted from Test::Memory::Cycle for Test2::API
sub memory_cycle_ok ($ref, $msg=undef) {

$msg ||= 'no memory cycle';

my($cycle_no, @diags) = _find_cycle($ref);

my $ok = !$cycle_no;

my $ctx = context();
Expand Down Expand Up @@ -115,6 +121,50 @@ sub _ref_shortname ($ref) {
return $refdisp;
}

=head2 no_memory_cycle

is(
$got,
hash {
no_memory_cycle;
}
);

Used in the context of a L<Test2::Tools::Compare> comparison. The whole test will fail with
appropriate diagnostics if there is a memory cycle in C<$got>.

=cut

sub no_memory_cycle () {
my @caller = caller;

## only using wantarray to error if called in void or list context
#croak "called in void context, probably a bug in your test." unless defined wantarray; ## no critic (Community::Wantarray)
#croak "called in list context, probably a bug in your test." if wantarray; ## no critic (Community::Wantarray)

return Test2::Tools::MemoryCycle::NoMemoryCycleCompare->new(
file => $caller[1],
lines => [$caller[2]],
);

}

package Test2::Tools::MemoryCycle::NoMemoryCycleCompare;

use parent 'Test2::Compare::Base';

sub name ($self) {
return 'memory cycle';
}

sub verify ($self, %p) {
return $p{exists} ? 1 : 0;
}

sub deltas ($self, %p) {
...
}

1;

=head1 CAVEATS
Expand Down
1 change: 1 addition & 0 deletions t/00_diag.t
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ $modules{$_} = $_ for qw(
ExtUtils::MakeMaker
PadWalker
Test2::API
Test2::Compare::Base
Test2::V0
);

Expand Down
Loading