Web site stress test with Perl - perl

What is the best way to test a site with Perl? How can I emulate a lot of connections to check how my script works on heavy load? Maybe there is a nice module on CPAN?
I am not interested in testing for dead links or 404 errors, only in work speed.

I have written these before so I can help you but it seems pretty straight forward for example:
use LWP::Simple;
my #urls ;
while($in=<>) {
push #urls,$in ;
$start=time();
for (i=0;i++; i< 99999999) {
use LWP::Simple;
my $content = get $url;
die if (/error/ ~= $content) ;
## Decide if you want to look at anything else
}
$stop=time() ;
## Write a report

Related

Accept POST parameters with FCGI

I am trying to get URL parameters using CGI and FCGI.
When executing the script on my browser I am only getting parameters of my first request, but the request $count does increment.
use CGI;
use FCGI;
my $fcgiRequest = FCGI::Request();
while ($fcgiRequest->Accept() >= 0)
{
print("Content-type: text/html\r\n\r\n", ++$count);
my $q = new CGI;
print "name = " . $q->param("name") ;
print "\n";
}
You can't use CGI.pm and FCGI.pm together like this. You need some glue-code in between, because CGI needs to read stuff from the environment, and it can't in the way you invoke it.
There is a module CGI::Fast included with Perl that does this for you. Instead of using CGI and FCGI, you just use CGI::Fast and change a bit of code.
use strict;
use warnings;
use CGI::Fast;
my $count;
while (my $q = CGI::Fast->new) {
# $q is a fresh CGI object for the current request
print("Content-type: text/html\r\n\r\n", ++$count);
print "name = " . $q->param("name") ;
print "\n";
}
If you already have a CGI script, you could put that in a function and call it inside of that loop.
If you're interested in how CGI::Fast works, feel free to take a look at its source code on CPAN. The main thing is that the environment and the file handles (for STDOUT and STDERR) need to be mapped to each new request, while your implementation has CGI always parse the first one.
Please note that the examples in both the perldoc and on CPAN that I have linked are very out-of-date and don't represent modern Perl code.
Today, you would probably not use CGI any more, as it has been removed from current Perl releases. Instead, you could take a look at the PSGI interface specification and Plack on how to implement it. The good thing about that is that it provides a clear interface across different deployment-technologies (such as CGI and Fast CGI). You can just let your program run as a simple CGI with Apache or nginx, or as a persistent FCGI process with Apache or other webservers, or as a standalone application through various Plack webservers that are written in Perl and are tailored for specific purposes.
Once a CGI.pm object is created for a request, it's reused there on out.
You can reset CGI.pm by adding the following to the end of the loop:
CGI::_reset_globals();

For/foreach loop crashing CGI server

I need to write some perl scripts for a class which include some for or foreach loops. For some reason even the simplest for loop are just returning a 500 server error. I've checked many times and the code also works on codepad.org, but I dont know why it is not working on the server.
I dont have access to the server logs so I can't really tell whats going on.
These are some very simple loops that are also causing the error.
#a=(2,3,4);
foreach my $r (#a) {
print $r;
}
or
#a=(2,3,4);
for ($i = 0; $i <= 2 ; $i++) {
print $a[$i];
}
Any ideas?
Any time you are writing a CGI script, put this at the top while you are working on it:
use CGI::Carp qw(fatalsToBrowser);
This will give redirect errors in your Perl script to the browser window. It should give you a better idea of what is causing your problem (assuming it is at the script level).
It also lets you easily send your own errors and test statements to the browser using die:
die "testing 1 2 3";
This can be useful for doing quick debugging.

Perl script to access a webpage

I have a server from which I can access a webpage. I want to test the server reaction when several users(say 60000 users) access the same webpage simultanously.
Im looking for a script to do this,a perl script will be better,
Here is the code I tried with
#!c:\\perl\\bin
use strict;
use WWW::Mechanize;
my $url = "http://www.cpan.org";
my $searchstring = "WWW::Mechanize";
my $mech = WWW::Mechanize->new();
while (i == 60000)
{
$mech->get($url);
i++;
}
But this scripts access the url 1 at a time, But I need simultanous access.
You can use ab. Use its concurrency (-c) and number of requests (-n) options.
Your code, as shown above, doesn't even compile. It would be far easier for people to help you if you gave us the exact code that you're using, rather than typing to retype it and adding typos.
To get your code to compile, I had to declare $i and add the $ before the two uses of i in your programme. I ended up with this:
#!/usr/bin/perl
use strict;
use WWW::Mechanize;
my $url = "http://www.cpan.org";
my $searchstring = "WWW::Mechanize";
my $mech = WWW::Mechanize->new();
my $i;
while ($i == 60000) {
$mech->get($url);
$i++;
}
You say that the loop only gets executed once. That's not true. The loop doesn't get executed at all. The condition on the loop is $i == 60000. The first time this condition is checked, $i is undefined so the condition is false and the loop is skipped.
I think you probably wanted $i <= 60000 instead.
But as Alan points out, you'd be far better off using an existing tool like ab.
You can either use Perl itself to launch your script 6000 times in parallel or write one (or maybe more than one) .BAT files or similar Windows scripting to launch the perl script.
Be careful to clearly understand how to execute stuff in detached mode under Windows.
(Of course you have to remove the while loop in your original script).
ab has already been mentioned, but that only tests against the root page (/) of the site. We found siege more useful in replicating real load, since we were able to test against a long list of URLs (10,000 or so) taken from our live access log...

Perl script to automate a website for bioinformatics

I would like to automate this website with a Perl script
http://bioinfo.uni-plovdiv.bg/microinspector/
This is what I have so far and I am not sure how to get to the output page after this, I know it has something to do with POST, redirect_ok?, response(), but I am not sure. I read through the documentation but am confused about some things. Thanks.
use strict;
use warnings;
use WWW::Mechanize;
# create object for browser
my $browser = WWW::Mechanize->new();
my ($sequence, $results);
open (DRG, "<microRNA_target_cspg_drg_output.fa") || die "cannot open microRNA_target_cspg_drg_output.fa";
while (<DRG>) {
chomp;
$sequence=$_;
last; #for testing purposes
}
close (DRG);
$browser->get("http://bioinfo.uni-plovdiv.bg/microinspector/");
$browser->form_number(1);
$browser->field("target_sequence", $sequence);
$browser->field("Choose an organism : ", "Mus musculus");
$browser->click_button( number => 1);
You should start with WWW::Mechanize. It's page provides examples on submitting forms, and anything else you will need.
EDIT: as a reply to your update, if you want to get the content of the page, use the content method, like in this example:
my $content = $browser->content();
See this for more info.

What Perl module can I use to test CGI output for common errors?

Is there a Perl module which can test the CGI output of another program? E.g. I have a program
x.cgi
(this program is not in Perl) and I want to run it from program
test_x_cgi.pl
So, e.g. test_x_cgi.pl is something like
#!perl
use IPC::Run3
run3 (("x.cgi"), ...)
So in test_x_cgi.pl I want to automatically check that the output of x.cgi doesn't do stupid things like, e.g. print messages before the HTTP header is fully outputted. In other words, I want to have a kind of "browser" in Perl which processes the output. Before I try to create such a thing myself, is there any module on CPAN which does this?
Please note that x.cgi here is not a Perl script; I am trying to write a test framework for it in Perl. So, specifically, I want to test a string of output for ill-formedness.
Edit: Thanks
I have already written a module which does what I want, so feel free to answer this question for the benefit of other people, but any further answers are academic as far as I'm concerned.
There's CGI::Test, which looks like what you're looking for. It specifically mentions the ability to test non-Perl CGI programs. It hasn't been updated for a while, but neither has the CGI spec.
There is Test::HTTP. I have not used it, but seems to have an interface that fits your requirements.
$test->header_is($header_name, $value [, $description]);
Compares the response header
$header_name with the value $value
using Test::Builder-is>.
$test->header_like($header_name, $regex, [, $description]);
Compares the response header
$header_name with the regex $regex
using Test::Builder-like>.
Look at the examples from chapter 16 from the perl cookbook
16.9. Controlling the Input, Output, and Error of Another Program
It uses IPC::Open3.
Fom perl cookbook, might be modified by me, see below.
Example 16.2
cmd3sel - control all three of kids in, out, and error.
use IPC::Open3;
use IO::Select;
$cmd = "grep vt33 /none/such - /etc/termcap";
my $pid = open3(*CMD_IN, *CMD_OUT, *CMD_ERR, $cmd);
$SIG{CHLD} = sub {
print "REAPER: status $? on $pid\n" if waitpid($pid, 0) > 0
};
#print CMD_IN "test test 1 2 3 \n";
close(CMD_IN);
my $selector = IO::Select->new();
$selector->add(*CMD_ERR, *CMD_OUT);
while (my #ready = $selector->can_read) {
foreach my $fh (#ready) {
if (fileno($fh) == fileno(CMD_ERR)) {print "STDERR: ", scalar <CMD_ERR>}
else {print "STDOUT: ", scalar <CMD_OUT>}
$selector->remove($fh) if eof($fh);
}
}
close(CMD_OUT);
close(CMD_ERR);
If you want to check that the output of x.cgi is properly formatted HTML/XHTML/XML/etc, why not run it through the W3 Validator?
You can download the source and find some way to call it from your Perl test script. Or, you might able to leverage this Perl interface to calling the W3 Validator on the web.
If you want to write a testing framework, I'd suggest taking a look at Test::More from CPAN as a good starting point. It's powerful but fairly easy to use and is definitely going to be better than cobbling something together as a one-off.