File: PherkinStream.pm

package info (click to toggle)
libtest-bdd-cucumber-perl 0.87-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 716 kB
  • sloc: perl: 4,493; makefile: 8
file content (123 lines) | stat: -rw-r--r-- 2,876 bytes parent folder | download
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
use v5.14;
use warnings;

package TAP::Parser::Iterator::PherkinStream 0.87;

=head1 NAME

TAP::Parser::Iterator::PherkinStream - Stream with TAP from async BDD process

=head1 VERSION

version 0.87

=cut


use base 'TAP::Parser::Iterator';

use IO::Select;

sub _initialize {
    my ($self, $out_fh, $err_fh, $pherkin, $child_pid) = @_;

    $self->{pherkin}   = $pherkin;
    $self->{child_pid} = $child_pid;
    $self->{sel}       = IO::Select->new($out_fh, $err_fh);
    $self->{out_fh}    = $out_fh;
    $self->{err_fh}    = $err_fh;

    return $self;
}

sub _finish {
    my $self = shift;

    $self->{pherkin}->_post_run();
    if ($self->{child_pid}) {
        waitpid $self->{child_pid}, 0; # reap child process
        $self->{wait} = $?;
        $self->{exit} = $? >> 8;
    }

    return $self;
}

sub wait { shift->{wait} }
sub exit { shift->{exit} }

sub _next {
    my $self = shift;

    my @buf = ();
    my $part = '';
    return sub {
        return shift @buf if @buf;

        while (my @ready = $self->{sel}->can_read) {
            for my $fh (@ready) {
                my $stderr = '';

              READ:
                {
                    my $got = sysread $fh, my ($chunk), 2048;
                    if ($got == 0) {
                        $self->{sel}->remove($fh);
                    }
                    elsif ($fh == $self->{err_fh}) {
                        $stderr .= $chunk;
                        my @lines = split(/\n/, $stderr, -1);
                        $stderr = pop @lines;

                        for my $line (@lines) {
                            utf8::decode($line);
                            print STDERR $line . "\n";
                        }
                        goto READ if $got == 2048;

                        utf8::decode($stderr)
                            or die 'Subprocess provided non-utf8 data';
                        print STDERR $stderr . "\n";
                    }
                    else {
                        $part .= $chunk;
                        push @buf, split(/\n/, $part, -1);
                        $part = pop @buf;

                        my $rv = shift @buf;
                        if (defined $rv) {
                            utf8::decode($rv)
                                or die 'Subprocess provided non-utf8 data';
                            return $rv;
                        }
                    }
                }
            }
        }

        if ($part) {
            $part = '';
            return $part;
        }

        $self->_finish;
        return;
    };
}

sub next_raw {
    my $self = shift;
    $self->{_next} ||= $self->_next;
    return $self->{_next}->();
}

sub get_select_handles {
    my $self = shift;

    # return our handle in case it's a socket or pipe (select()-able)
    return ( $self->{out_fh}, $self->{err_fh});
}



1;