stas        2003/08/26 21:42:38

  Modified:    t/filter in_str_consume.t
               t/filter/TestFilter in_str_consume.pm
  Log:
  rewrite the input streaming consume filter to bring it up-to-date with the
  latest httpds. make it more elaborate at the same time.
  
  Revision  Changes    Path
  1.3       +7 -4      modperl-2.0/t/filter/in_str_consume.t
  
  Index: in_str_consume.t
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/filter/in_str_consume.t,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- in_str_consume.t  18 Apr 2003 06:18:56 -0000      1.2
  +++ in_str_consume.t  27 Aug 2003 04:42:37 -0000      1.3
  @@ -1,6 +1,8 @@
   use strict;
   use warnings FATAL => 'all';
   
  +# see the explanations in in_str_consume.pm
  +
   use Apache::Test;
   use Apache::TestUtil;
   use Apache::TestRequest;
  @@ -9,10 +11,11 @@
   
   my $location = '/TestFilter__in_str_consume';
   
  -# send a message bigger than 8k, so to make sure that the input filter
  -# will get more than one bucket brigade with data.
  -my $data = "A 22 chars long string" x 500; # about 11k
  +my $data = "*" x 80000; # about 78K => ~10 bbs
  +my $expected = 105;
  +
  +t_debug "sent "  . length($data) . "B, expecting ${expected}B to make through";
  +
   my $received = POST_BODY $location, content => $data;
  -my $expected = "read just the first 1024b from the first brigade";
   
   ok t_cmp($expected, $received, "input stream filter partial consume")
  
  
  
  1.8       +77 -44    modperl-2.0/t/filter/TestFilter/in_str_consume.pm
  
  Index: in_str_consume.pm
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/t/filter/TestFilter/in_str_consume.pm,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- in_str_consume.pm 22 Aug 2003 19:15:08 -0000      1.7
  +++ in_str_consume.pm 27 Aug 2003 04:42:38 -0000      1.8
  @@ -2,65 +2,94 @@
   
   # this test verifies that streaming filters framework handles
   # gracefully the case when a filter doesn't print anything at all to
  -# the caller. I figure it absolutely doesn't matter if the incoming
  -# bb from the upstream is consumed or not. What matters is that the
  -# filter sends something downstream (an empty bb will do).
  -#
  +# the caller.
  +
   # the real problem is that in the streaming filters we can't consume
  -# more than one bucket brigade, which we can in non-stream filters.,
  -# e.g. see in_bbs_underrun.pm
  +# more than one bucket brigade during a single filter invocation,
  +# which we can in non-stream filters., (e.g. see in_bbs_underrun.pm)
  +#
  +# it seems that this works just fine (2.0.46+) and older httpds
  +# had problems when a filter invocation hasn't printed a thing.
  +#
  +# currently if the streaming filter doesn't print anything, the
  +# upstream filter gets an empty brigade brigade (easily verified with
  +# the snooping debug filter). Of course if the filter returns
  +# Apache::DECLINED the unconsumed data will be passed to upstream filter
  +#
  +# this test receives about 10 bbs
  +# it reads only the first 23 bytes of each bb and discards the rest
  +# since it wants only 105 bytes it partially consumes only the first 5 bbs
  +# since it doesn't read all the data in, it'll never see EOS
  +# therefore once it has read all 105 bytes, it manually sets the EOS flag
  +# and the rest of the bbs are ignored, the filter is invoked only 5 times
  +#
  +# to debug this filter run it as:
  +#
  +# t/TEST -v -trace=debug filter/in_str_consume
  +#
  +# to enable upstream and downstream filter snooping, uncomment the
  +# snooping filters directives at the end of this file and rerun:
  +# t/TEST -conf
  +#
  +# to see what happens inside the filter, assuming that you built
  +# mod_perl with MP_TRACE=1, run:
  +# env MOD_PERL_TRACE=f t/TEST -v -trace=debug filter/in_str_consume
   #
  -# e.g. a filter that cleans up the incoming stream (extra spaces?)
  -# might reduce the whole bb into nothing (e.g. if it was made of only
  -# white spaces) then it should send "" down.
  -#
  -# another problem with not reading in the while() loop, is that the
  -# eos bucket won't be detected by the streaming framework and
  -# consequently won't be sent downstream, probably breaking other
  -# filters who rely on receiving the EOS bucket.
   
   use strict;
   use warnings FATAL => 'all';
   
   use Apache::Filter ();
  +use Apache::TestTrace;
   
   use Apache::Const -compile => qw(OK M_POST);
   
  +use constant READ_BYTES_TOTAL => 105;
  +use constant READ_BYTES_FIRST => 23;
  +
   sub handler {
       my $filter = shift;
   
  -    my $count = $filter->ctx || 0;
  +    my $ctx = $filter->ctx || { data => '', count => '1'};
  +    debug "FILTER INVOKED: $ctx->{count}";
  +
  +    # read untill READ_BYTES read, no matter how many filter
  +    # invocations it'll take
  +    my $wanted_total   = READ_BYTES_TOTAL - length $ctx->{data};
  +    my $wanted_current = READ_BYTES_FIRST;
  +    my $wanted = $wanted_total;
  +    $wanted = $wanted_current if $wanted > $wanted_current;
  +    debug "total wanted:   $wanted_total bytes";
  +    debug "this bb wanted: $wanted bytes";
  +    while ($wanted) {
  +        my $len = $filter->read(my $buffer, $wanted);
  +        $ctx->{data} .= $buffer;
  +        $wanted_total -= $len;
  +        $wanted       -= $len;
  +        debug "FILTER READ: $len ($wanted_total more to go)";
  +        last unless $len; # no more data to read in this bb
  +    }
  +
  +    $ctx->{count}++;
   
  -    unless ($count) {
  -        # read a bit from the first brigade and leave the second
  -        # brigade completely unconsumed. we assume that there are two
  -        # brigades because the core input filter will split data in
  -        # 8kb chunks per brigade and we have sent 11k of data (1st bb:
  -        # 8kb, 2nd bb: ~3kb)
  -        my $len = $filter->read(my $buffer, 1024);
  -        #warn "FILTER READ: $len bytes\n";
  -        $filter->print("read just the first 1024b from the first brigade");
  +    unless ($wanted_total) {
  +        # we don't want to read the rest if there is anything left
  +        $filter->seen_eos(1);
  +    }
   
  -        $filter->ctx(1);
  +    if ($filter->seen_eos) {
  +        # flush the data if we are done
  +        $filter->print($ctx->{data});
       }
       else {
  -        $count++;
  -        #warn "FILTER CALLED post $count time\n";
  -        unless ($filter->seen_eos) {
  -            # XXX: comment out the next line to reproduce the segfault
  -            $filter->print("");
  -            $filter->ctx($count);
  -        }
  -
  -        # this is not needed in newer Apache versions, however older
  -        # versions (2.0.40) will repeatedly call this filter, waiting
  -        # for EOS which will never come from this filter so, after
  -        # several invocations mark the seen_eos flag, to break the
  -        # vicious cirle
  -        # BACK_COMPAT_MARKER: make back compat issues easy to find
  -        if ($count > 10) {
  -            $filter->seen_eos(1);
  -        }
  +        # store the data away
  +        $filter->ctx($ctx);
  +
  +        # notice that it seems to work even though we don't print
  +        # anything. the upstream filter gets an empty bb.
  +
  +        # alternatively could print the chunks of data that we read,
  +        # if we don't need to have it as a whole chunk
       }
   
       return Apache::OK;
  @@ -73,8 +102,9 @@
   
       if ($r->method_number == Apache::M_POST) {
           my $data = ModPerl::Test::read_post($r);
  -        #warn "HANDLER READ: $data\n";
  -        $r->print($data);
  +        my $len = length $data;
  +        debug "HANDLER READ: $len bytes\n";
  +        $r->print($len);
       }
   
       return Apache::OK;
  @@ -84,3 +114,6 @@
   SetHandler modperl
   PerlModule          TestFilter::in_str_consume
   PerlResponseHandler TestFilter::in_str_consume::response
  +#PerlInputFilterHandler  ModPerl::TestFilterDebug::snoop_request
  +PerlInputFilterHandler  TestFilter::in_str_consume::handler
  +#PerlInputFilterHandler  ModPerl::TestFilterDebug::snoop_request
  
  
  

Reply via email to