rprove 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #!/usr/bin/env perl
  2. package App::Prove::Remote::rprove;
  3. use strict;
  4. use warnings;
  5. if( !caller() ) {
  6. $ENV{'RPROVE_HOST'} ? exit remote_shim() : exit run();
  7. }
  8. sub run {
  9. my ( $host, $workdir, $interpreter ) = ( '127.0.0.1', 0, '', '/usr/bin/perl' );
  10. require App::Prove;
  11. require Getopt::Long;
  12. Getopt::Long::Configure( 'auto_help', 'pass_through' );
  13. Getopt::Long::GetOptions(
  14. 'host|h=s' => \$host,
  15. 'workdir=s' => \$workdir,
  16. 'interpreter=s' => \$interpreter,
  17. );
  18. # Set ENV bitz
  19. local @ENV{qw{RPROVE_HOST RPROVE_WORK_DIR RPROVE_INTERPRETER}} = ($host, $workdir, $interpreter);
  20. my $prove_args = { 'exec' => $0 };
  21. my $prove = App::Prove->new($prove_args);
  22. $prove->process_args(@ARGV);
  23. $prove->merge(1);
  24. # Run prove
  25. return $prove->run ? 0 : 1;
  26. }
  27. sub remote_shim {
  28. require Net::OpenSSH;
  29. my $host = $ENV{'RPROVE_HOST'} || '127.0.0.1';
  30. my $wd = $ENV{'RPROVE_WORK_DIR'} || '';
  31. my $bin = $ENV{'RPROVE_INTERPRETER'} || '/usr/bin/perl';
  32. my $test = $ARGV[0] || die "No test passed in!";
  33. my $ssh = Net::OpenSSH->new($host);
  34. # Print directly to stdout, as this function merges
  35. # STDOUT & STDERR and discards STDIN.
  36. # Do this to avoid TTY overflow, and because prove expects
  37. # to capture output from STDOUT/ERR anyways.
  38. my $system_opts = {
  39. 'stdout_discard' => 0,
  40. 'stderr_discard' => 0,
  41. 'stderr_to_stdout' => 1,
  42. 'stdin_discard' => 1,
  43. };
  44. # Optionally move to the working directory, run the test.
  45. my $cd = $wd ? "cd $wd && " : '';
  46. $ssh->system( $system_opts, "${cd}${bin} '$wd/$test'" );
  47. # Net::OpenSSH sets this value correctly for our purposes here.
  48. return $?;
  49. }
  50. 1;
  51. __END__
  52. =head1 NAME
  53. rprove - Prove wrapper which executes your tests on the remote host
  54. =head1 SYNOPSIS
  55. rprove [options] [file ...]
  56. Options:
  57. -help You are reading it!
  58. -host Host to connect to. Defaults to 127.0.0.1.
  59. -workdir Directory to change to before running test(s).
  60. -interpreter Path on remote to test running interpreter. Defaults to /usr/bin/perl
  61. =head1 OPTIONS
  62. =over 8
  63. =item B<-help>
  64. Print a brief help message and exits.
  65. =item B<-host>
  66. Host to connect to. Defaults to 127.0.0.1
  67. =item B<-wordkir>
  68. Directory to execute the test from. Useful to set if the test requires it.
  69. =item B<-interpreter>
  70. Path to the interpreter to run your tests with. Default is /usr/bin/perl.
  71. Useful to set if you have perl in a nonstandard location
  72. or non-perl tests to execute that still emit valid TAP.
  73. =back
  74. =head1 DESCRIPTION
  75. B<rprove> will locally run prove with a --exec argument which is a shim.
  76. This (remote_shim mode) will connect to the remote host for the test in
  77. question and run it on the host.
  78. Why do this? Because sometimes testing certain scenarios is better done
  79. on a disposable remote environment instead of on the local environment.
  80. If someone has a "smoker" like environment (Jenkins, some other CI) which
  81. also runs your tests, this could also be of use from the orchestrator's
  82. end.
  83. Anyways, the user is responsible for ensuring the test (and code under
  84. test) has been properly deployed to the remote system under test, so
  85. make sure that's done first if you want this approach to work.
  86. Output of the script is then read by the TAP parser as is expected for
  87. a seamless testing experience *as if you had ran the test locally*.
  88. =cut