File: bucket.pm

package info (click to toggle)
libapache2-mod-perl2 2.0.9~1624218-2%2Bdeb8u2
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 11,912 kB
  • ctags: 4,588
  • sloc: perl: 95,064; ansic: 14,527; makefile: 49; sh: 18
file content (211 lines) | stat: -rw-r--r-- 6,152 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
package TestAPRlib::bucket;

# a mix of APR::Bucket and APR::BucketType tests

use strict;
use warnings FATAL => 'all';

use Apache::Test;
use Apache::TestUtil;
use TestCommon::Utils;

use APR::Pool ();
use APR::Bucket ();
use APR::BucketAlloc ();
use APR::BucketType ();
use APR::Table ();

use APR::Const -compile => 'SUCCESS';

sub num_of_tests {
    return 21;
}

sub test {

    my $pool = APR::Pool->new();
    my $ba   = APR::BucketAlloc->new($pool);

    # new: basic
    {
        my $data = "foobar";
        my $b = APR::Bucket->new($ba, $data);

        t_debug('$b is defined');
        ok defined $b;

        t_debug('$b ISA APR::Bucket object');
        ok $b->isa('APR::Bucket');

        my $type = $b->type;
        ok t_cmp $type->name, 'mod_perl SV bucket', "type";

        ok t_cmp $b->length, length($data), "modperl b->length";
    }

    # new: offset
    {
        my $data   = "foobartar";
        my $offset = 3;
        my $real = substr $data, $offset;
        my $b = APR::Bucket->new($ba, $data, $offset);
        my $rlen = $b->read(my $read);
        ok t_cmp $read, $real, 'new($data, $offset)/buffer';
        ok t_cmp $rlen, length($read), 'new($data, $offset)/len';
        ok t_cmp $b->start, $offset, 'offset';

    }

    # new: offset+len
    {
        my $data   = "foobartar";
        my $offset = 3;
        my $len    = 3;
        my $real = substr $data, $offset, $len;
        my $b = APR::Bucket->new($ba, $data, $offset, $len);
        my $rlen = $b->read(my $read);
        ok t_cmp $read, $real, 'new($data, $offset, $len)/buffer';
        ok t_cmp $rlen, length($read), 'new($data, $offse, $lent)/len';
    }

    # new: offset+ too big len
    {
        my $data   = "foobartar";
        my $offset = 3;
        my $len    = 10;
        my $real = substr $data, $offset, $len;
        my $b = eval { APR::Bucket->new($ba, $data, $offset, $len) };
        ok t_cmp $@,
            qr/the length argument can't be bigger than the total/,
            'new($data, $offset, $len_too_big)';
    }

    # modification of the source variable, affects the data
    # inside the bucket
    {
        my $data = "A" x 10;
        my $orig = $data;
        my $b = APR::Bucket->new($ba, $data);
        $data =~ s/^..../BBBB/;
        $b->read(my $read);
        ok t_cmp $read, $data,
            "data inside the bucket should get affected by " .
            "the changes to the Perl variable it's created from";
    }


    # APR::Bucket->new() with the argument PADTMP (which happens when
    # some function is re-entered) and the same SV is passed to
    # different buckets, which must be detected and copied away.
    {
        my @buckets  = ();
        my @data     = qw(ABCD EF);
        my @received = ();
        for my $str (@data) {
            my $b = func($ba, $str);
            push @buckets, $b;
        }

        # the creating of buckets and reading from them is done
        # separately on purpose
        for my $b (@buckets) {
            $b->read(my $out);
            push @received, $out;
        }

        # here we used to get: two pv: "ef\0d"\0, "ef"\0, as you can see
        # the first bucket had corrupted data.
        my @expected = map { lc } @data;
        ok t_cmp \@received, \@expected, "new(PADTMP SV)";

        # this function will pass the same SV to new(), causing two
        # buckets point to the same SV, and having the latest bucket's
        # data override the previous one
        sub func {
            my $ba = shift;
            my $data = shift;
            return APR::Bucket->new($ba, lc $data);
        }

    }

    # read data is tainted
    {
        my $data = "xxx";
        my $b = APR::Bucket->new($ba, $data);
        $b->read(my $read);
        ok t_cmp $read, $data, 'new($data)';
        ok TestCommon::Utils::is_tainted($read);
    }

    # remove/destroy
    {
        my $b = APR::Bucket->new($ba, "aaa");
        # remove $b when it's not attached to anything (not sure if
        # that should be an error)
        $b->remove;
        ok 1;

        # a dangling bucket needs to be destroyed
        $b->destroy;
        ok 1;

        # real remove from bb is tested in many other filter tests
    }

    # setaside
    {
        my $data = "A" x 10;
        my $expected = $data;
        my $b = APR::Bucket->new($ba, $data);
        my $status = $b->setaside($pool);
        ok t_cmp $status, APR::Const::SUCCESS, "setaside status";
        $data =~ s/^..../BBBB/;
        $b->read(my $read);
        ok t_cmp $read, $expected,
            "data inside the setaside bucket is unaffected by " .
            "changes to the Perl variable it's created from";
        $b->destroy;
    }

    # alloc_create on out-of-scope pools
    {
        # later may move that into a dedicated bucket_alloc test
        my $ba = APR::BucketAlloc->new(APR::Pool->new);
        # here if the pool is gone of scope destroy() will segfault
        $ba->destroy;
        ok 1;
    }

    # setaside on out-of-scope pools
    {
        # note that at the moment APR internally handles the situation
        # when the pool goes out of scope, so modperl doesn't need to do
        # any special handling of the pool object passed to setaside()
        # to insure that it survives as long as $b is alive
        #
        # to make sure that this doesn't change internally in APR, the
        # sub-test remains here
        my $data = "A" x 10;
        my $orig = $data;
        my $b = APR::Bucket->new($ba, $data);
        my $status = $b->setaside(APR::Pool->new);
        ok t_cmp $status, APR::Const::SUCCESS, "setaside status";

        # try to overwrite the temp pool data
        my $table = APR::Table::make(APR::Pool->new, 50);
        $table->set($_ => $_) for 'aa'..'za';

        # now test that we are still OK
        $b->read(my $read);
        ok t_cmp $read, $data,
            "data inside the setaside bucket is not corrupted";
        $b->destroy;
    }

    $ba->destroy;
}

1;