| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Test2::Plugin::IOMuxer; | 
| 2 | 2 |  |  | 2 |  | 206741 | use strict; | 
|  | 2 |  |  |  |  | 6 |  | 
|  | 2 |  |  |  |  | 55 |  | 
| 3 | 2 |  |  | 2 |  | 11 | use warnings; | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 83 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | our $VERSION = '0.000008'; | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 2 |  |  | 2 |  | 372 | use Test2::Plugin::OpenFixPerlIO; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 53 |  | 
| 9 | 2 |  |  | 2 |  | 870 | use Test2::Plugin::IOMuxer::Layer; | 
|  | 2 |  |  |  |  | 7 |  | 
|  | 2 |  |  |  |  | 58 |  | 
| 10 | 2 |  |  | 2 |  | 973 | use Test2::Plugin::IOMuxer::STDERR; | 
|  | 2 |  |  |  |  | 8 |  | 
|  | 2 |  |  |  |  | 56 |  | 
| 11 | 2 |  |  | 2 |  | 817 | use Test2::Plugin::IOMuxer::STDOUT; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 54 |  | 
| 12 | 2 |  |  | 2 |  | 766 | use Test2::Plugin::IOMuxer::FORMAT; | 
|  | 2 |  |  |  |  | 7 |  | 
|  | 2 |  |  |  |  | 81 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 2 |  |  | 2 |  | 15 | use IO::Handle; | 
|  | 2 |  |  |  |  | 6 |  | 
|  | 2 |  |  |  |  | 84 |  | 
| 15 |  |  |  |  |  |  |  | 
| 16 | 2 |  |  |  |  | 99 | use Test2::API qw{ | 
| 17 |  |  |  |  |  |  | test2_add_callback_post_load | 
| 18 |  |  |  |  |  |  | test2_stack | 
| 19 | 2 |  |  | 2 |  | 11 | }; | 
|  | 2 |  |  |  |  | 5 |  | 
| 20 |  |  |  |  |  |  |  | 
| 21 | 2 |  |  | 2 |  | 12 | use Carp qw/confess/; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 170 |  | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | our @EXPORT_OK = qw/mux_handle/; | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | sub import { | 
| 26 | 1 |  |  | 1 |  | 5925 | my $class = shift; | 
| 27 | 1 |  |  |  |  | 4 | my ($in) = @_; | 
| 28 |  |  |  |  |  |  |  | 
| 29 | 1 | 50 |  |  |  | 6 | return unless $in; | 
| 30 | 1 | 50 |  |  |  | 6 | if ($in eq 'mux_handle') { | 
| 31 | 1 |  |  |  |  | 3 | my $caller = caller; | 
| 32 | 2 |  |  | 2 |  | 12 | no strict 'refs'; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 879 |  | 
| 33 | 1 |  |  |  |  | 4 | *{"$caller\::mux_handle"} = \&mux_handle; | 
|  | 1 |  |  |  |  | 6 |  | 
| 34 | 1 |  |  |  |  | 4 | return 1; | 
| 35 |  |  |  |  |  |  | } | 
| 36 |  |  |  |  |  |  |  | 
| 37 | 0 |  |  |  |  | 0 | my $file = $in; | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 0 |  |  |  |  | 0 | mux_handle(\*STDOUT, $file, 'Test2::Plugin::IOMuxer::STDOUT'); | 
| 40 | 0 |  |  |  |  | 0 | mux_handle(\*STDERR, $file, 'Test2::Plugin::IOMuxer::STDERR'); | 
| 41 |  |  |  |  |  |  |  | 
| 42 | 0 | 0 |  |  |  | 0 | mux_handle(Test2::API::test2_stdout(), $file, 'Test2::Plugin::IOMuxer::STDOUT') if Test2::API->can('test2_stdout'); | 
| 43 | 0 | 0 |  |  |  | 0 | mux_handle(Test2::API::test2_stderr(), $file, 'Test2::Plugin::IOMuxer::STDERR') if Test2::API->can('test2_stderr'); | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | test2_add_callback_post_load(sub { | 
| 46 | 0 |  |  | 0 |  | 0 | my @handles; | 
| 47 |  |  |  |  |  |  |  | 
| 48 | 0 |  |  |  |  | 0 | my $hub = test2_stack()->top; | 
| 49 | 0 | 0 |  |  |  | 0 | my $formatter = $hub->format or next; | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 0 |  |  |  |  | 0 | for my $meth (qw/handles io/) { | 
| 52 | 0 | 0 |  |  |  | 0 | if ($formatter->can($meth)) { | 
| 53 | 0 |  |  |  |  | 0 | my @list = $formatter->$meth; | 
| 54 | 0 | 0 | 0 |  |  | 0 | @list = @{$list[0]} if @list == 1 && ref($list[0]) eq 'ARRAY'; | 
|  | 0 |  |  |  |  | 0 |  | 
| 55 | 0 |  |  |  |  | 0 | push @handles => @list; | 
| 56 |  |  |  |  |  |  | } | 
| 57 |  |  |  |  |  |  | } | 
| 58 |  |  |  |  |  |  |  | 
| 59 | 0 |  |  |  |  | 0 | mux_handle($_, $file, 'Test2::Plugin::IOMuxer::FORMAT') for @handles; | 
| 60 | 0 |  |  |  |  | 0 | }); | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | sub mux_handle(*$;$) { | 
| 65 | 1 |  |  | 1 | 0 | 1503 | my ($fh, $file, $layer) = @_; | 
| 66 |  |  |  |  |  |  |  | 
| 67 | 1 |  | 50 |  |  | 15 | $layer ||= 'Test2::Plugin::IOMuxer::Layer'; | 
| 68 |  |  |  |  |  |  |  | 
| 69 | 1 |  |  |  |  | 5 | my $fileno = fileno($_[0]); | 
| 70 | 1 | 50 |  |  |  | 7 | die "Could not get fileno for handle" unless defined $fileno; | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 1 | 50 |  |  |  | 7 | if (my $set = $Test2::Plugin::IOMuxer::Layer::MUXED{$fileno}) { | 
| 73 | 0 | 0 |  |  |  | 0 | return if $set eq $file; | 
| 74 | 0 |  |  |  |  | 0 | confess "Handle (fileno: $fileno) already muxed to '$set', cannot mux to '$file'"; | 
| 75 |  |  |  |  |  |  | } | 
| 76 |  |  |  |  |  |  |  | 
| 77 | 1 |  |  |  |  | 7 | $Test2::Plugin::IOMuxer::Layer::MUXED{$fileno} = $file; | 
| 78 |  |  |  |  |  |  |  | 
| 79 | 1 | 50 |  |  |  | 7 | unless($Test2::Plugin::IOMuxer::Layer::MUX_FILES{$file}) { | 
| 80 | 1 | 50 |  |  |  | 9 | open(my $mh, '>', $file) or die "Could not open mux file '$file': $!"; | 
| 81 | 1 |  |  |  |  | 16 | $mh->autoflush(1); | 
| 82 | 1 |  |  |  |  | 99 | $Test2::Plugin::IOMuxer::Layer::MUX_FILES{$file} = $mh; | 
| 83 |  |  |  |  |  |  | } | 
| 84 |  |  |  |  |  |  |  | 
| 85 | 1 |  |  | 1 |  | 8 | binmode($_[0], ":via($layer)"); | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 1 |  |  |  |  | 25 |  | 
| 86 |  |  |  |  |  |  | } | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | 1; | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | __END__ |