aboutsummaryrefslogtreecommitdiffstats
path: root/testing/lib/Test/Irssi/Driver.pm
diff options
context:
space:
mode:
Diffstat (limited to 'testing/lib/Test/Irssi/Driver.pm')
-rw-r--r--testing/lib/Test/Irssi/Driver.pm258
1 files changed, 258 insertions, 0 deletions
diff --git a/testing/lib/Test/Irssi/Driver.pm b/testing/lib/Test/Irssi/Driver.pm
new file mode 100644
index 0000000..6b4e5e5
--- /dev/null
+++ b/testing/lib/Test/Irssi/Driver.pm
@@ -0,0 +1,258 @@
+use strictures 1;
+
+package Test::Irssi::Driver;
+
+use Moose;
+use lib $ENV{HOME} . "/projects/poe/lib";
+
+use POE qw( Wheel::ReadWrite Wheel::Run Filter::Stream );
+use POSIX;
+use feature qw/say/;
+use Data::Dump qw/dump/;
+
+has 'parent'
+ => (
+ is => 'ro',
+ isa => 'Test::Irssi',
+ required => 1,
+ );
+
+has 'headless'
+ => (
+ is => 'rw',
+ isa => 'Bool',
+ default => 0,
+ );
+
+sub START {
+ my ($self, $kernel, $heap) = @_[OBJECT, KERNEL, HEAP];
+
+ $kernel->alias_set("IrssiTestDriver");
+
+ $self->log("Start handler called");
+
+ $self->save_term_settings($heap);
+
+ # Set a signal handler.
+ $kernel->sig(CHLD => "got_sigchld");
+
+ $self->make_raw_terminal;
+
+ my @stdio_options =
+ (
+ InputHandle => \*STDIN,
+ OutputHandle => \*STDOUT,
+ InputEvent => "got_terminal_stdin",
+ Filter => POE::Filter::Stream->new(),
+ );
+
+ $self->log("stdio options: " . dump(@stdio_options));
+
+ # Start the terminal reader/writer.
+ $heap->{stdio} = POE::Wheel::ReadWrite->new(@stdio_options);
+
+ $self->log("Created stdio wheel");
+
+ my $rows = $self->parent->terminal_height;
+ my $cols = $self->parent->terminal_width;
+
+ my @program_options =
+ (
+ Program => $self->parent->irssi_binary,
+ ProgramArgs => ['--noconnect', '--home=' . $self->parent->irssi_homedir ],
+ Conduit => "pty",
+ Winsize => [$rows, $cols, 0, 0],
+ StdoutEvent => "got_child_stdout",
+ StdioFilter => POE::Filter::Stream->new(),
+ );
+
+ $self->log("wheel options: " . dump(@program_options));
+
+ # Start the asynchronous child process.
+ $heap->{program} = POE::Wheel::Run->new(@program_options);
+
+ $self->log("Created child run wheel");
+ $poe_kernel->yield('testing_ready');
+}
+
+sub STOP {
+ my ($self, $heap) = @_[OBJECT,HEAP];
+ $self->log("STOP called");
+ $self->restore_term_settings($heap);
+ $self->parent->_logfile_fh->close();
+
+ if (not $self->parent->generate_tap) {
+ $self->parent->summarise_test_results();
+ }
+}
+
+### Handle terminal STDIN. Send it to the background program's STDIN.
+### If the user presses ^C, then echo a little string
+
+sub terminal_stdin {
+ my ($self, $heap, $input) = @_[OBJECT, HEAP, ARG0];
+
+ if ($input =~ m/\003/g) { # C-c
+ $input = "/echo I like cakes\n";
+ } elsif ($input =~ m/\x17/g) { # C-w
+ $input = "/quit\n";
+ }
+
+ $heap->{program}->put($input);
+}
+
+### Handle STDOUT from the child program.
+sub child_stdout {
+ my ($self, $heap, $input) = @_[OBJECT, HEAP, ARG0];
+ # process via vt
+ $self->parent->vt->process($input);
+
+ if (not $self->headless) {
+ # send to terminal
+ $heap->{stdio}->put($input);
+ }
+}
+
+### Handle SIGCHLD. Shut down if the exiting child process was the
+### one we've been managing.
+
+sub shutdown {
+ my ($self, $heap, $kernel) = @_[OBJECT, HEAP, KERNEL];
+ $self->log("Shutdown called");
+ $heap->{program}->kill(15);
+ $kernel->alias_remove("IrssiTestDriver");
+}
+
+sub CHILD {
+ my ($self, $heap, $child_pid) = @_[OBJECT, HEAP, ARG1];
+ if ($child_pid == $heap->{program}->PID) {
+ delete $heap->{program};
+ delete $heap->{stdio};
+ }
+ return 0;
+}
+
+sub setup {
+ my $self = shift;
+
+ my @states =
+ (
+ object_states =>
+ [ $self =>
+ {
+ _start => 'START',
+ _stop => 'STOP',
+ got_sigchld => 'CHILD',
+
+ got_terminal_stdin => 'terminal_stdin',
+ got_child_stdout => 'child_stdout',
+
+ got_delay => 'timer_expired',
+ create_delay => 'timer_created',
+
+
+ testing_ready => 'testing_ready',
+ test_complete => 'test_complete',
+ execute_test => 'execute_test',
+
+ shutdown => 'shutdown',
+ }
+ ]
+ );
+ $self->log("creating root session");
+
+ POE::Session->create(@states);
+ $self->log("session created");
+
+}
+
+sub testing_ready {
+ my ($self) = $_[OBJECT];
+ # begin by fetching a test from the pending queue.
+ $self->log("Starting to run tests");
+ $self->log("-" x 80);
+ $self->parent->run_test;
+}
+
+sub execute_test {
+ my ($self, $heap, $kernel, $test) = @_[OBJECT,HEAP, KERNEL, ARG0];
+ # do some stuff here to evaluate it.
+
+ $test->evaluate_test;
+
+}
+
+sub test_complete {
+ my ($self, $kernel) = @_[OBJECT, KERNEL];
+
+ $self->parent->complete_test;
+
+ if ($self->parent->tests_remaining) {
+ $self->parent->run_test;
+ }
+
+ # otherwise, we're done, and can shutdown.
+ #kernel->yield('shutdown');
+
+}
+
+sub timer_created {
+ my ($self, $heap, $kernel, $duration) = @_[OBJECT, HEAP, KERNEL, ARG0];
+ $kernel->delay(got_delay => $duration);
+ $self->log("Timer created for $duration");
+}
+
+sub timer_expired {
+ my ($self, $data) = @_[OBJECT,ARG0];
+ $self->log("Timeout invoking test again.");
+ $self->parent->active_test->resume_from_timer;
+}
+
+sub save_term_settings {
+ my ($self, $heap) = @_;
+ # Save the original terminal settings so they can be restored later.
+ $heap->{stdin_tio} = POSIX::Termios->new();
+ $heap->{stdin_tio}->getattr(0);
+ $heap->{stdout_tio} = POSIX::Termios->new();
+ $heap->{stdout_tio}->getattr(1);
+ $heap->{stderr_tio} = POSIX::Termios->new();
+ $heap->{stderr_tio}->getattr(2);
+}
+
+sub restore_term_settings {
+ my ($self, $heap) = @_;
+
+ $heap->{stdin_tio}->setattr (0, TCSANOW);
+ $heap->{stdout_tio}->setattr(1, TCSANOW);
+ $heap->{stderr_tio}->setattr(2, TCSANOW);
+}
+
+sub make_raw_terminal {
+ my ($self) = @_;
+ # Put the terminal into raw input mode. Otherwise discrete
+ # keystrokes will not be read immediately.
+ my $tio = POSIX::Termios->new();
+ $tio->getattr(0);
+ my $lflag = $tio->getlflag;
+ $lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN | ISIG);
+ $tio->setlflag($lflag);
+ my $iflag = $tio->getiflag;
+ $iflag &= ~(BRKINT | INPCK | ISTRIP | IXON);
+ $tio->setiflag($iflag);
+ my $cflag = $tio->getcflag;
+ $cflag &= ~(CSIZE | PARENB);
+ $tio->setcflag($cflag);
+ $tio->setattr(0, TCSANOW);
+}
+
+sub log {
+ my ($self, $msg) = @_;
+ my $fh = $self->parent->_logfile_fh;
+ $fh->say($msg);
+}
+
+
+__PACKAGE__->meta->make_immutable;
+
+no Moose;
+