# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl 5.t' ######################### use Test::More tests => 62; #use Test::More qw(no_plan); BEGIN { use_ok('Net::BEEP::Lite::MgmtProfile'); use_ok('Net::BEEP::Lite::Message'); use_ok('Net::BEEP::Lite::Session'); use_ok('XML::LibXML'); }; ######################### # Testing Net::BEEP::Lite::MgmtProfile # the constructor: my $mgmt = Net::BEEP::Lite::MgmtProfile->new; ok(defined $mgmt, 'constructor works'); isa_ok($mgmt, 'Net::BEEP::Lite::MgmtProfile'); isa_ok($mgmt, 'Net::BEEP::Lite::BaseProfile'); $mgmt = Net::BEEP::Lite::MgmtProfile->new(AllowMultipleChannels => 1); is($mgmt->allow_multiple_channels(), 1, 'mgmt->allow_multiple_channels()'); $mgmt->allow_multiple_channels(0); is($mgmt->allow_multiple_channels(), 0, 'mgmt->allow_multiple_channels($val)'); # test the management message creation routines. # for that, we need some (fake) profiles. my $fake_profile = { uri => "http://host.example.com/some/profile" }; bless $fake_profile, 'Net::BEEP::Lite::BaseProfile'; # a session. my $session = new Net::BEEP::Lite::Session(); $session->add_local_profile($fake_profile); # and an XML parser. my $parser = XML::LibXML->new(); # The greeting message. my $msg = $mgmt->greeting_message($session->get_local_profile_uris()); isa_ok($msg, 'Net::BEEP::Lite::Message', 'mgmt->greeting_message()'); is($msg->content_type(), 'application/beep+xml', 'greeting message content type'); is($msg->type(), 'RPY', 'greeting message is a RPY'); my $root = $parser->parse_string($msg->content())->documentElement(); is($root->nodeName, "greeting", 'greeting msg is greeting element'); my @children = $root->childNodes; for my $child (@children) { if ($child->isa('XML::LibXML::Element')) { is($child->nodeName, "profile", 'and has profile child element'); is($child->getAttribute('uri'), "http://host.example.com/some/profile", 'and has profile with correct uri'); } } # the start channel message $msg = $mgmt->start_channel_message (URI => "http://host.example.com/some/profile", Channel => 1, ServerName => "host.example.com", StartData => "starting data"); is($msg->type(), 'MSG', 'start message is MSG'); $root = $parser->parse_string($msg->content())->documentElement(); is($root->nodeName, "start", "start message has start element"); is($root->getAttribute('number'), 1, 'has expected channel number'); is($root->getAttribute('serverName'), 'host.example.com', 'has serverName'); @children = $root->childNodes; for my $child (@children) { if ($child->isa('XML::LibXML::Element')) { is($child->nodeName, "profile", 'has profile child element'); is($child->getAttribute('uri'), 'http://host.example.com/some/profile', 'has correct profile uri'); is($child->textContent, 'starting data', 'has starting data'); } } # the close channel message. my $close_content = 'this is some close content'; $msg = $mgmt->close_channel_message(1, 220, $close_content, 'en-US'); is($msg->type(), 'MSG', 'close message is MSG'); $root = $parser->parse_string($msg->content())->documentElement(); is($root->nodeName, 'close', 'close message has close element'); is($root->getAttribute('number'), 1, 'has correct channel number'); is($root->getAttribute('code'), 220, 'has correct code attribute'); is($root->textContent, $close_content, 'has correct text content'); # profile message my $profile_data = "response to start data"; $msg = $mgmt->profile_message(11, 'http://host.example.com/some/profile', $profile_data, 0); is($msg->type(), 'RPY', 'profile message is RPY'); $root = $parser->parse_string($msg->content())->documentElement(); is($root->nodeName, 'profile', 'has profile element'); is($root->getAttribute('uri'), 'http://host.example.com/some/profile', 'has correct URI'); is($root->textContent, $profile_data, 'and has correct profile content'); # error message creation $msg = $mgmt->_error_message(11, 543, 'some error content'); is($msg->type(), 'ERR', 'error messages are ERR'); is($msg->content_type(), 'application/beep+xml', 'has correct content type'); $root = $parser->parse_string($msg->content())->documentElement(); is($root->nodeName, 'error', 'has error element'); is($root->getAttribute('code'), 543, 'has correct code attribute.'); is($root->textContent, 'some error content', 'has correct error content'); ## Testing the profile itself. # for this, we need to fake the socket. We do this with IO::Stringy, # which is optional. So we will skip the tests if it is not # available. SKIP: { eval { require IO::Lines; }; skip "IO::Stringy (and specifically IO::Lines) not installed", 26 if $@; my @output_lines; $session->{sock} = new IO::Lines(\@output_lines); sub msg_from_lines { my $header = shift; my $frame = new Net::BEEP::Lite::Frame(Header => $header); my $payload = join('', @_); $frame->set_payload(substr($payload, 0, $frame->size())); new Net::BEEP::Lite::Message(Frame => $frame); } # For now, we mainly test correct cases. It is a known TODO to # check and handle more errors in general. # MSGs. These include start and close message. my $uri = $fake_profile->uri(); my $channel_zero = $session->channel(0); my $orig_window = $channel_zero->remote_window(); # the greeting message. @output_lines = (); $channel_zero->remote_window($orig_window); $mgmt->send_greeting_message($session); $msg = msg_from_lines(@output_lines); is($msg->type(), 'RPY', 'sent greeting message was RPY'); $root = $parser->parse_string($msg->content())->documentElement(); is($root->nodeName, "greeting", 'greeting msg is greeting element'); my @children = $root->childNodes; for my $child (@children) { if ($child->isa('XML::LibXML::Element')) { is($child->nodeName, "profile", 'and has profile child element'); is($child->getAttribute('uri'), "http://host.example.com/some/profile", 'and has profile with correct uri'); } } @output_lines = (); $channel_zero->remote_window($orig_window); $mgmt->handle_message($session, $msg); is(scalar @output_lines, 0, 'greeting message generated no response'); # the start message. # FIXME: we should test startChannelData, but our fake session # doesn't have a real profile that can handle it. my ($open_channel_num) = $mgmt->send_start_channel_message($session, (URI => $uri, ServerName => "host.example.com")); my $msg = msg_from_lines(@output_lines); is($session->{starting_channel_number}, $open_channel_num, 'send_start_channel_message set "starting_channel_number" ' . 'in the session'); my $msgno = $msg->msgno(); ok($msgno > 0, "send_start_channel_message assigned msgno: $msgno"); @output_lines = (); $channel_zero->remote_window($orig_window); $mgmt->handle_message($session, $msg); my $resp = msg_from_lines(@output_lines); is($resp->type(), 'RPY', 'response to start channel is RPY'); is($resp->content_type, 'application/beep+xml', 'has correct content type'); is($resp->msgno(), $msgno, 'has correct message number'); $root = $parser->parse_string($resp->content())->documentElement(); is($root->nodeName, 'profile', 'and is a profile element'); # send a second start channel request that should be refused. $mgmt->allow_multiple_channels(0); @output_lines = (); $channel_zero->remote_window($orig_window); $msg->reset_frames(); $msg->msgno($msgno + 1); $mgmt->handle_message($session, $msg); $resp = msg_from_lines(@output_lines); is($resp->type(), 'ERR', 'response to disallowed start channel is ERR'); is($resp->msgno(), $msg->msgno(), 'has correct message number'); $root = $parser->parse_string($resp->content)->documentElement(); is($root->nodeName, 'error', 'and is an error element'); # The close message # close our just opened channel. @output_lines = (); $channel_zero->remote_window($orig_window); $mgmt->send_close_channel_message($session, $open_channel_num); $msg = msg_from_lines(@output_lines); is($msg->type(), 'MSG', 'sent close channel message was MSG'); is($msg->channel_number(), 0, 'sent close channel message was on chan. zero'); is($session->{closing_channel_number}, $open_channel_num, 'send_close_channel_message set "closing_channel_number" in the session'); $msgno = $msg->msgno(); @output_lines = (); $channel_zero->remote_window($orig_window); $mgmt->handle_message($session, $msg); $resp = msg_from_lines(@output_lines); is($resp->type(), 'RPY', 'response to close message is RPY'); is($resp->msgno(), $msgno, 'has correct message number'); is($resp->channel_number(), 0, "has correct channel number"); $root = $parser->parse_string($resp->content)->documentElement(); is($root->nodeName, 'ok', 'has an ok element'); # Replies: this includes greeting, profile, and ok responses. # lets create a greeting with multiple advertised profiles. To do # that, we need to add some more (fake) profiles to our session my $fake_profile2 = { uri => "http://host.example.com/some/profile2" }; bless $fake_profile2, 'Net::BEEP::Lite::BaseProfile'; my $fake_profile3 = { uri => "http://host.example.com/some/profile3" }; bless $fake_profile3, 'Net::BEEP::Lite::BaseProfile'; $session->add_local_profile($fake_profile2); $session->add_local_profile($fake_profile3); @output_lines = (); $channel_zero->remote_window($orig_window); $mgmt->send_greeting_message($session); $msg = msg_from_lines(@output_lines); is($msg->msgno(), 0, 'greeting always is message 0 for us'); $mgmt->handle_message($session, $msg); ok($session->has_remote_profile('http://host.example.com/some/profile3'), 'has third remote profile'); ok($session->has_remote_profile('http://host.example.com/some/profile2'), 'has second remote profile'); ok($session->has_remote_profile('http://host.example.com/some/profile'), 'has first remote profile'); # profile @output_lines = (); $channel_zero->remote_window($orig_window); # note that this test is pretty feeble. $mgmt->send_profile_message($session, 16, 'http://host.example.com/some/profile2'); $msg = msg_from_lines(@output_lines); # we have to fake the starting channel number bit. this would # normally be set by the send_start_channel_message routine. $session->{starting_channel_number} = 7; @output_lines = (); $channel_zero->remote_window($orig_window); $mgmt->handle_message($session, $msg); $new_channel = $session->channel(7); ok($new_channel, 'profile message added channel'); }