#!/usr/bin/perl -w # # Test the new reused thunks # use strict; use warnings; use Test::More; sub POE::Kernel::ASSERT_EVENTS { 1 } sub POE::Component::IKC::OLD_PROXY_SENDER { 0 } my $N = 1; plan tests => 5+5*$N; use POE::Component::IKC::Server; use POE::Component::IKC::Channel; use POE::Component::IKC::Client; use POE::Wheel::Run; use POE qw(Kernel); pass( "loaded" ); sub DEBUG () { 0 } DEBUG and print "Starting servers...\n"; my $port = POE::Component::IKC::Server->spawn( port => 0, name => 'Inet', aliases => [qw(Ikc)] ); Test::Runner->spawn( $port, $N ); $poe_kernel->run(); pass( "Sane shutdown" ); ############################################################################ package Test::Runner; use strict; use Config; use POE::Session; BEGIN { *ok=\&::ok; *DEBUG=\&::DEBUG; } ########################################################### sub spawn { my($package, $port, $N)=@_; POE::Session->create( args=>[$port, $N], package_states=>[ $package=>[qw(_start _stop other_register other_unregister done shutdown do_child timeout post1 post2 post2b post3 done child_stdout child_stderr sig_child )], ], ); } ########################################################### sub _start { my($kernel, $heap, $port, $N)=@_[KERNEL, HEAP, ARG0, ARG1]; DEBUG and warn "Server: _start\n"; ::pass( '_start' ); $kernel->alias_set('test'); $kernel->call(IKC=>'publish', test=>[qw( post1 post2 post2b post3 done )] ); $heap->{port} = $port; $heap->{N} = $N; $kernel->post(IKC=>'monitor', '*'=>{shutdown=>'shutdown'}); # ::diag( "Launch $N clients" ); foreach ( 1 .. $N ) { $kernel->call( $_[SESSION], do_child=>'thunk'); } } ########################################################### sub do_child { my($kernel, $heap, $type)=@_[KERNEL, HEAP, ARG0]; my $wheel = POE::Wheel::Run->new( Program => sub { t::ChildThunk->run( $heap->{port}, $type ) }, StdoutEvent => 'child_stdout', StderrEvent => 'child_stderr' ); my $pid = $wheel->PID; my $name = "\u$type${pid}Client"; $kernel->sig_child( $pid => 'sig_child' ); $kernel->delay(timeout=>60); $kernel->post(IKC=>'monitor', $name=>{ register=>'other_register', unregister=>'other_unregister' }); $heap->{W}{$wheel->ID} = $wheel; $heap->{P}{$wheel->PID} = $wheel->ID; return; } sub sig_child { my( $heap, $sig, $pid ) = @_[ HEAP, ARG0, ARG1 ]; DEBUG and warn "sig_child $pid"; my $wid = delete $heap->{P}{$pid}; delete $heap->{W}{$wid}; return; } sub child_stdout { my( $heap, $input, $wid ) = @_[ HEAP, ARG0, ARG1 ]; print "$input\n"; } sub child_stderr { my( $heap, $input, $wid ) = @_[ HEAP, ARG0, ARG1 ]; print STDERR "$input\n"; } ########################################################### sub _stop { my($kernel, $heap)=@_[KERNEL, HEAP, ARG0]; DEBUG and warn "Server: _stop ($$)\n"; # ::pass('_stop'); } ########################################################### sub other_register { my($kernel, $heap, $name, $alias, $is_alias, )=@_[KERNEL, HEAP, ARG0, ARG1, ARG2]; $heap->{connected}++; DEBUG and warn "Server: other_register\n"; # ::is($name, 'InetClient'); } ########################################################### sub other_unregister { my($kernel, $heap, $name, $alias, $is_alias, )=@_[KERNEL, HEAP, ARG0, ARG1, ARG2]; $heap->{connected}--; DEBUG and warn "Server: other_unregister ($name)"; ok( ( $heap->{connected} >= 0 ), "Never less then zero ($heap->{connected})" ); $kernel->delay('timeout'); $heap->{connections}++; if( $heap->{connections} == $heap->{N} ) { # delete $heap->{W}; $kernel->post( IKC=>"shutdown" ); } } ########################################################### sub shutdown { my($kernel, $heap, $name, $alias, $is_alias, )=@_[KERNEL, HEAP, ARG0, ARG1, ARG2]; $kernel->alias_remove('test'); DEBUG and warn "Server: shutdown\n"; ::pass('shutdown'); } ########################################################### sub timeout { my($kernel)=$_[KERNEL]; die "Server: Timedout waiting for child process.\n"; $kernel->post(IKC=>'shutdown'); } ########################################################### sub post1 { my($kernel, $heap, $arg)=@_[KERNEL, HEAP, ARG0]; DEBUG and warn "Server: post1 $arg\n"; $heap->{sender} = $_[SENDER]->ID; $kernel->post( $_[SENDER], resp1 => $arg ); } ########################################################### sub post2 { my($kernel, $sender, $heap, $arg)=@_[KERNEL, SENDER, HEAP, ARG0]; DEBUG and warn "Server: post2 $arg\n"; ::is( $sender->ID, $heap->{sender}, "Same thunk" ); $kernel->refcount_increment( $sender->ID, "hold on" ); $kernel->yield( 'post2b', $arg ); } ########################################################### sub post2b { my( $kernel, $heap, $arg ) = @_[KERNEL, HEAP, ARG0]; DEBUG and warn "Server: post2b $arg\n"; $kernel->post( $heap->{sender}, resp2 => $arg ); } ########################################################### sub post3 { my($kernel, $heap, $sender, $arg)=@_[KERNEL, HEAP, SENDER, ARG0]; ::isnt( $sender->ID, $heap->{sender}, "New thunk" ); $heap->{sender2} = $sender->ID; $kernel->post($sender, resp3 => $arg); } ########################################################### sub done { my($kernel, $heap, $sender)=@_[KERNEL, HEAP, SENDER]; ::isnt( $sender->ID, $heap->{sender}, "Not first thunk" ); ::is( $sender->ID, $heap->{sender2}, "2nd thunk" ); $kernel->refcount_decrement( $heap->{sender}, "hold on" ); DEBUG and warn "Server: done\n"; ::pass( 'done' ); } ############################################################################### package t::ChildThunk; use strict; use warnings; sub DEBUG () {0} use POE::Component::IKC::ClientLite; sub run { my( $package, $port, $type ) = @_; $port ||= 1337; $type ||= 'thunk'; my $name = "\u$type$$".'Client'; DEBUG and warn "$$: Connect\n"; my $poe=create_ikc_client( port=>$port, name=>$name, ); die $POE::Component::IKC::ClientLite::error unless $poe; DEBUG and warn "$$: post1\n"; $poe->post('test/post1', "the") or die $poe->error; DEBUG and warn "$$: resp1\n"; my( $n ) = $poe->responded( 'resp1' ); defined( $n ) or die $poe->error; $n eq 'the' or die "No! n=$n"; DEBUG and warn "$$: post2\n"; $poe->post('test/post2', "wizard") or die $poe->error; DEBUG and warn "$$: resp2\n"; ( $n ) = $poe->responded( 'resp2' ); defined( $n ) or die $poe->error; $n eq 'wizard' or die "No! n=$n"; DEBUG and warn "$$: post3\n"; $poe->post('test/post3', "walks bye") or die $poe->error; DEBUG and warn "$$: resp3\n"; ( $n ) = $poe->responded( 'resp3' ); defined( $n ) or die $poe->error; $n eq 'walks bye' or die "No! n=$n"; DEBUG and warn "$$: done\n"; $poe->post('test/done', "walks bye") or die $poe->error; DEBUG and warn "$$: disconnect\n"; $poe->disconnect; # for real DEBUG and warn "$$: Client exiting\n"; } __END__