PageRenderTime 17ms CodeModel.GetById 13ms app.highlight 1ms RepoModel.GetById 1ms app.codeStats 0ms

/Test-Refcount-0.07/README

#
#! | 155 lines | 118 code | 37 blank | 0 comment | 0 complexity | ccf973c63ecd57feb5bbea91fce5fde1 MD5 | raw file
  1NAME
  2    "Test::Refcount" - assert reference counts on objects
  3
  4SYNOPSIS
  5     use Test::More tests => 2;
  6     use Test::Refcount;
  7
  8     use Some::Class;
  9
 10     my $object = Some::Class->new();
 11
 12     is_oneref( $object, '$object has a refcount of 1' );
 13
 14     my $otherref = $object;
 15
 16     is_refcount( $object, 2, '$object now has 2 references' );
 17
 18DESCRIPTION
 19    The Perl garbage collector uses simple reference counting during the
 20    normal execution of a program. This means that cycles or unweakened
 21    references in other parts of code can keep an object around for longer
 22    than intended. To help avoid this problem, the reference count of a new
 23    object from its class constructor ought to be 1. This way, the caller
 24    can know the object will be properly DESTROYed when it drops all of its
 25    references to it.
 26
 27    This module provides two test functions to help ensure this property
 28    holds for an object class, so as to be polite to its callers.
 29
 30    If the assertion fails; that is, if the actual reference count is
 31    different to what was expected, a trace of references to the object can
 32    be printed, if Marc Lehmann's Devel::FindRef module is installed. This
 33    may assist the developer in finding where the references are. See the
 34    examples below for more information.
 35
 36FUNCTIONS
 37  is_refcount( $object, $count, $name )
 38    Test that $object has $count references to it.
 39
 40  is_oneref( $object, $name )
 41    Assert that the $object has only 1 reference to it.
 42
 43EXAMPLE
 44    Suppose, having written a new class "MyBall", you now want to check that
 45    its constructor and methods are well-behaved, and don't leak references.
 46    Consider the following test script:
 47
 48     use Test::More tests => 2;
 49     use Test::Refcount;
 50 
 51     use MyBall;
 52 
 53     my $ball = MyBall->new();
 54     is_oneref( $ball, 'One reference after construct' );
 55 
 56     $ball->bounce;
 57
 58     # Any other code here that might be part of the test script
 59 
 60     is_oneref( $ball, 'One reference just before EOF' );
 61
 62    The first assertion is just after the constructor, to check that the
 63    reference returned by it is the only reference to that object. This fact
 64    is important if we ever want "DESTROY" to behave properly. The second
 65    call is right at the end of the file, just before the main scope closes.
 66    At this stage we expect the reference count also to be one, so that the
 67    object is properly cleaned up.
 68
 69    Suppose, when run, this produces the following output (presuming
 70    "Devel::FindRef" is available):
 71
 72     1..2
 73     ok 1 - One reference after construct
 74     not ok 2 - One reference just before EOF
 75     #   Failed test 'One reference just before EOF'
 76     #   at demo.pl line 16.
 77     #   expected 1 references, found 2
 78     # MyBall=ARRAY(0x817f880) is
 79     # +- referenced by REF(0x82c1fd8), which is
 80     # |     in the member 'self' of HASH(0x82c1f68), which is
 81     # |        referenced by REF(0x81989d0), which is
 82     # |           in the member 'cycle' of HASH(0x82c1f68), which was seen before.
 83     # +- referenced by REF(0x82811d0), which is
 84     #       in the lexical '$ball' in CODE(0x817fa00), which is
 85     #          the main body of the program.
 86     # Looks like you failed 1 test of 2.
 87
 88    From this output, we can see that the constructor was well-behaved, but
 89    that a reference was leaked by the end of the script - the reference
 90    count was 2, when we expected just 1. Reading the trace output, we can
 91    see that there were 2 references that "Devel::FindRef" could find - one
 92    stored in the $ball lexical in the main program, and one stored in a
 93    HASH. Since we expected to find the $ball lexical variable, we know we
 94    are now looking for a leak in a hash somewhere in the code. From reading
 95    the test script, we can guess this leak is likely to be in the bounce()
 96    method. Furthermore, we know that the reference to the object will be
 97    stored in a HASH in a member called "self".
 98
 99    By reading the code which implements the bounce() method, we can see
100    this is indeed the case:
101
102     sub bounce
103     {
104        my $self = shift;
105        my $cycle = { self => $self };
106        $cycle->{cycle} = $cycle;
107     }
108
109    From reading the "Devel::FindRef" output, we find that the HASH this
110    object is referenced in also contains a reference to itself, in a member
111    called "cycle". This comes from the last line in this function, a line
112    that purposely created a cycle, to demonstrate the point. While a real
113    program probably wouldn't do anything quite this obvious, the trace
114    would still be useful in finding the likely cause of the leak.
115
116    If "Devel::FindRef" is unavailable, then these detailed traces will not
117    be produced. The basic reference count testing will still take place,
118    but a smaller message will be produced:
119
120     1..2
121     ok 1 - One reference after construct
122     not ok 2 - One reference just before EOF
123     #   Failed test 'One reference just before EOF'
124     #   at demo.pl line 16.
125     #   expected 1 references, found 2
126     # Looks like you failed 1 test of 2.
127
128BUGS
129    *   Temporaries created on the stack
130
131        Code which creates temporaries on the stack, to be released again
132        when the called function returns does not work correctly on perl 5.8
133        (and probably before). Examples such as
134
135         is_oneref( [] );
136
137        may fail and claim a reference count of 2 instead.
138
139        Passing a variable such as
140
141         my $array = [];
142         is_oneref( $array );
143
144        works fine. Because of the intention of this test module; that is,
145        to assert reference counts on some object stored in a variable
146        during the lifetime of the test script, this is unlikely to cause
147        any problems.
148
149ACKNOWLEDGEMENTS
150    Peter Rabbitson <ribasushi@cpan.org> - for suggesting using core's "B"
151    instead of "Devel::Refcount" to obtain refcounts
152
153AUTHOR
154    Paul Evans <leonerd@leonerd.org.uk>
155