summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/perl/cpan/Test-Simple/t/lib/Test/Builder/NoOutput.pm
blob: 62c97ecb0f3e20fd4ea2535323dffcb71933ada5 (plain) (blame)
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
package Test::Builder::NoOutput;

use strict;
use warnings;

use Symbol qw(gensym);
use base qw(Test::Builder);


=head1 NAME

Test::Builder::NoOutput - A subclass of Test::Builder which prints nothing

=head1 SYNOPSIS

    use Test::Builder::NoOutput;

    my $tb = Test::Builder::NoOutput->new;

    ...test as normal...

    my $output = $tb->read;

=head1 DESCRIPTION

This is a subclass of Test::Builder which traps all its output.
It is mostly useful for testing Test::Builder.

=head3 read

    my $all_output = $tb->read;
    my $output     = $tb->read($stream);

Returns all the output (including failure and todo output) collected
so far.  It is destructive, each call to read clears the output
buffer.

If $stream is given it will return just the output from that stream.
$stream's are...

    out         output()
    err         failure_output()
    todo        todo_output()
    all         all outputs

Defaults to 'all'.

=cut

my $Test = __PACKAGE__->new;

sub create {
    my $class = shift;
    my $self = $class->SUPER::create(@_);

    require Test::Builder::Formatter;
    $self->{Stack}->top->format(Test::Builder::Formatter->new);

    my %outputs = (
        all  => '',
        out  => '',
        err  => '',
        todo => '',
    );
    $self->{_outputs} = \%outputs;

    my($out, $err, $todo) = map { gensym() } 1..3;
    tie *$out,  "Test::Builder::NoOutput::Tee", \$outputs{all}, \$outputs{out};
    tie *$err,  "Test::Builder::NoOutput::Tee", \$outputs{all}, \$outputs{err};
    tie *$todo, "Test::Builder::NoOutput::Tee", \$outputs{all}, \$outputs{todo};

    $self->output($out);
    $self->failure_output($err);
    $self->todo_output($todo);

    return $self;
}


sub read {
    my $self = shift;
    my $stream = @_ ? shift : 'all';

    my $out = $self->{_outputs}{$stream};

    $self->{_outputs}{$stream} = '';

    # Clear all the streams if 'all' is read.
    if( $stream eq 'all' ) {
        my @keys = keys %{$self->{_outputs}};
        $self->{_outputs}{$_} = '' for @keys;
    }

    return $out;
}


package Test::Builder::NoOutput::Tee;

# A cheap implementation of IO::Tee.

sub TIEHANDLE {
    my($class, @refs) = @_;

    my @fhs;
    for my $ref (@refs) {
        my $fh = Test::Builder->_new_fh($ref);
        push @fhs, $fh;
    }

    my $self = [@fhs];
    return bless $self, $class;
}

sub PRINT {
    my $self = shift;

    print $_ @_ for @$self;
}

sub PRINTF {
    my $self   = shift;
    my $format = shift;

    printf $_ @_ for @$self;
}

1;