Server IP : 103.119.228.120 / Your IP : 3.144.115.125 Web Server : Apache System : Linux v8.techscape8.com 3.10.0-1160.119.1.el7.tuxcare.els2.x86_64 #1 SMP Mon Jul 15 12:09:18 UTC 2024 x86_64 User : nobody ( 99) PHP Version : 5.6.40 Disable Function : shell_exec,symlink,system,exec,proc_get_status,proc_nice,proc_terminate,define_syslog_variables,syslog,openlog,closelog,escapeshellcmd,passthru,ocinum cols,ini_alter,leak,listen,chgrp,apache_note,apache_setenv,debugger_on,debugger_off,ftp_exec,dl,dll,myshellexec,proc_open,socket_bind,proc_close,escapeshellarg,parse_ini_filepopen,fpassthru,exec,passthru,escapeshellarg,escapeshellcmd,proc_close,proc_open,ini_alter,popen,show_source,proc_nice,proc_terminate,proc_get_status,proc_close,pfsockopen,leak,apache_child_terminate,posix_kill,posix_mkfifo,posix_setpgid,posix_setsid,posix_setuid,dl,symlink,shell_exec,system,dl,passthru,escapeshellarg,escapeshellcmd,myshellexec,c99_buff_prepare,c99_sess_put,fpassthru,getdisfunc,fx29exec,fx29exec2,is_windows,disp_freespace,fx29sh_getupdate,fx29_buff_prepare,fx29_sess_put,fx29shexit,fx29fsearch,fx29ftpbrutecheck,fx29sh_tools,fx29sh_about,milw0rm,imagez,sh_name,myshellexec,checkproxyhost,dosyayicek,c99_buff_prepare,c99_sess_put,c99getsource,c99sh_getupdate,c99fsearch,c99shexit,view_perms,posix_getpwuid,posix_getgrgid,posix_kill,parse_perms,parsesort,view_perms_color,set_encoder_input,ls_setcheckboxall,ls_reverse_all,rsg_read,rsg_glob,selfURL,dispsecinfo,unix2DosTime,addFile,system,get_users,view_size,DirFiles,DirFilesWide,DirPrintHTMLHeaders,GetFilesTotal,GetTitles,GetTimeTotal,GetMatchesCount,GetFileMatchesCount,GetResultFiles,fs_copy_dir,fs_copy_obj,fs_move_dir,fs_move_obj,fs_rmdir,SearchText,getmicrotime MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/local/lib64/perl5/Test/ |
Upload File : |
package Test::LeakTrace; use 5.008_001; use strict; use warnings; our $VERSION = '0.15'; use XSLoader; XSLoader::load(__PACKAGE__, $VERSION); use Test::Builder::Module; our @ISA = qw(Test::Builder::Module); use Exporter qw(import); # use Exporter::import for backward compatibility our @EXPORT = qw( leaktrace leaked_refs leaked_info leaked_count no_leaks_ok leaks_cmp_ok count_sv ); our %EXPORT_TAGS = ( all => \@EXPORT, test => [qw(no_leaks_ok leaks_cmp_ok)], util => [qw(leaktrace leaked_refs leaked_info leaked_count count_sv)], ); sub _do_leaktrace{ my($block, $name, $need_stateinfo, $mode) = @_; if(!defined($mode) && !defined wantarray){ warnings::warnif void => "Useless use of $name() in void context"; } if($name eq 'leaked_count') { my $start; $start = count_sv(); $block->(); return count_sv() - $start; } local $SIG{__DIE__} = 'DEFAULT'; _start($need_stateinfo); eval{ $block->(); }; if($@){ _finish(-silent); die $@; } return _finish($mode); } sub leaked_refs(&){ my($block) = @_; return _do_leaktrace($block, 'leaked_refs', 0); } sub leaked_info(&){ my($block) = @_; return _do_leaktrace($block, 'leaked_refs', 1); } sub leaked_count(&){ my($block) = @_; return scalar _do_leaktrace($block, 'leaked_count', 0); } sub leaktrace(&;$){ my($block, $mode) = @_; _do_leaktrace($block, 'leaktrace', 1, defined($mode) ? $mode : -simple); return; } sub leaks_cmp_ok(&$$;$){ my($block, $cmp_op, $expected, $description) = @_; my $Test = __PACKAGE__->builder; if(!_runops_installed()){ my $mod = exists $INC{'Devel/Cover.pm'} ? 'Devel::Cover' : 'strange runops routines'; return $Test->ok(1, "skipped (under $mod)"); } # calls to prepare cache in $block $block->(); my $got = _do_leaktrace($block, 'leaked_count', 0); my $desc = sprintf 'leaks %s %-2s %s', $got, $cmp_op, $expected; if(defined $description){ $description .= " ($desc)"; } else{ $description = $desc; } my $result = $Test->cmp_ok($got, $cmp_op, $expected, $description); if(!$result){ open local(*STDERR), '>', \(my $content = ''); $block->(); # calls it again because opening *STDERR changes the run-time environment _do_leaktrace($block, 'leaktrace', 1, -verbose); $Test->diag($content); } return $result; } sub no_leaks_ok(&;$){ # ($block, $description) splice @_, 1, 0, ('<=', 0); # ($block, '<=', 0, $description); goto &leaks_cmp_ok; } 1; __END__ =for stopwords sv gfx =head1 NAME Test::LeakTrace - Traces memory leaks =head1 VERSION This document describes Test::LeakTrace version 0.15. =head1 SYNOPSIS use Test::LeakTrace; # simple report leaktrace{ # ... }; # verbose output leaktrace{ # ... } -verbose; # with callback leaktrace{ # ... } sub { my($ref, $file, $line) = @_; warn "leaked $ref from $file line\n"; }; my @refs = leaked_refs{ # ... }; my @info = leaked_info{ # ... }; my $count = leaked_count{ # ... }; # standard test interface use Test::LeakTrace; no_leaks_ok{ # ... } 'no memory leaks'; leaks_cmp_ok{ # ... } '<', 10; =head1 DESCRIPTION C<Test::LeakTrace> provides several functions that trace memory leaks. This module scans arenas, the memory allocation system, so it can detect any leaked SVs in given blocks. B<Leaked SVs> are SVs which are not released after the end of the scope they have been created. These SVs include global variables and internal caches. For example, if you call a method in a tracing block, perl might prepare a cache for the method. Thus, to trace true leaks, C<no_leaks_ok()> and C<leaks_cmp_ok()> executes a block more than once. =head1 INTERFACE =head2 Exported functions =head3 C<< leaked_info { BLOCK } >> Executes I<BLOCK> and returns a list of leaked SVs and places where the SVs come from, i.e. C<< [$ref, $file, $line] >>. =head3 C<< leaked_refs { BLOCK } >> Executes I<BLOCK> and returns a list of leaked SVs. =head3 C<< leaked_count { BLOCK } >> Executes I<BLOCK> and returns the number of leaked SVs. =head3 C<< leaktrace { BLOCK } ?($mode | \&callback) >> Executes I<BLOCK> and reports leaked SVs to C<*STDERR>. Defined I<$mode>s are: =over 4 =item -simple Default. Reports the leaked SV identity (type and address), file name and line number. =item -sv_dump In addition to B<-simple>, dumps the sv content using C<sv_dump()>, which also implements C<Devel::Peek::Dump()>. =item -lines In addition to B<-simple>, prints suspicious source lines. =item -verbose Both B<-sv_dump> and B<-lines>. =back =head3 C<< no_leaks_ok { BLOCK } ?$description >> Tests that I<BLOCK> does not leaks SVs. This is a test function using C<Test::Builder>. Note that I<BLOCK> is called more than once. This is because I<BLOCK> might prepare caches which are not memory leaks. =head3 C<< leaks_cmp_ok { BLOCK } $cmp_op, $number, ?$description >> Tests that I<BLOCK> leaks a specific number of SVs. This is a test function using C<Test::Builder>. Note that I<BLOCK> is called more than once. This is because I<BLOCK> might prepare caches which are not memory leaks. =head3 C<< count_sv() >> Counts all the SVs in the arena. =head2 Script interface Like C<Devel::LeakTrace> C<Test::LeakTrace::Script> is provided for whole scripts. The arguments of C<use Test::LeakTrace::Script> directive is the same as C<leaktrace()>. $ TEST_LEAKTRACE=-sv_dump perl -MTest::LeakTrace::Script script.pl $ perl -MTest::LeakTrace::Script=-verbose script.pl #!perl # ... use Test::LeakTrace::Script sub{ my($ref, $file, $line) = @_; # ... }; # ... =head1 EXAMPLES =head2 Testing modules Here is a test script template that checks memory leaks. #!perl -w use strict; use constant HAS_LEAKTRACE => eval{ require Test::LeakTrace }; use Test::More HAS_LEAKTRACE ? (tests => 1) : (skip_all => 'require Test::LeakTrace'); use Test::LeakTrace; use Some::Module; leaks_cmp_ok{ my $o = Some::Module->new(); $o->something(); $o->something_else(); } '<', 1; =head1 DEPENDENCIES Perl 5.8.1 or later, and a C compiler. =head1 CAVEATS C<Test::LeakTrace> does not work with C<Devel::Cover> and modules which install their own C<runops> routines, or the perl executor. So if the test functions of this module detect strange C<runops> routines, they do nothing and report okay. =head1 BUGS No bugs have been reported. Please report any bugs or feature requests to the author. =head1 SEE ALSO L<Devel::LeakTrace>. L<Devel::LeakTrace::Fast>. L<Test::TraceObject>. L<Test::Weak>. For guts: L<perlguts>. L<perlhack>. F<sv.c>. =head1 AUTHOR Goro Fuji(gfx) E<lt>gfuji(at)cpan.orgE<gt>. =head1 LICENSE AND COPYRIGHT Copyright (c) 2009-2010, Goro Fuji(gfx). All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut