Changeset 742

Show
Ignore:
Timestamp:
07/23/07 16:45:04 (1 year ago)
Author:
kindlund
Message:

Documentation and unit testing complete for FF browser.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • honeyclient/branches/exp/kindlund-firefox/lib/HoneyClient/Agent/Driver/Browser/FF.pm

    r723 r742  
    1 ############################################################################### 
     1####################################################################### 
    22# Created on:  May 11, 2006 
    33# Package:     HoneyClient::Agent::Driver::FF 
     
    99# CVS: $Id$ 
    1010# 
    11 # @author knwang, xkovah, kindlund, ttruong 
     11# @author knwang, ttruong, kindlund, stephenson 
    1212# 
    1313# Copyright (C) 2007 The MITRE Corporation.  All rights reserved. 
     
    2828# 02110-1301, USA. 
    2929# 
    30 ############################################################################### 
     30
     31####################################################################### 
     32 
     33=pod 
     34 
     35=head1 NAME 
     36 
     37HoneyClient::Agent::Driver::Browser::FF - Perl extension to drive Mozilla  
     38Firefox to a given web page.  This package extends the 
     39HoneyClient::Agent::Driver::Browser package, by overridding the drive() method. 
     40 
     41=head1 VERSION 
     42 
     43This documentation refers to HoneyClient::Agent::Driver::Browser::FF version 0.97. 
     44 
     45=head1 SYNOPSIS 
     46 
     47  use HoneyClient::Agent::Driver::Browser::FF; 
     48 
     49  # Library used exclusively for debugging complex objects. 
     50  use Data::Dumper; 
     51 
     52  # Create a new FF object, initialized with a collection 
     53  # of URLs to visit. 
     54  my $browser = HoneyClient::Agent::Driver::Browser::FF->new( 
     55      links_to_visit => { 
     56          'http://www.google.com'  => 1, 
     57          'http://www.cnn.com'     => 1, 
     58      }, 
     59  ); 
     60 
     61  # If you want to see what type of "state information" is physically 
     62  # inside $browser, try this command at any time. 
     63  print Dumper($browser); 
     64 
     65  # Continue to "drive" the driver, until it is finished. 
     66  while (!$browser->isFinished()) { 
     67 
     68      # Before we drive the application to a new set of resources, 
     69      # find out where we will be going within the application, first. 
     70      print "About to contact the following resources:\n"; 
     71      print Dumper($browser->next()); 
     72 
     73      # Now, drive browser for one iteration. 
     74      $browser->drive(); 
     75 
     76      # Get the driver's progress. 
     77      print "Status:\n"; 
     78      print Dumper($browser->status()); 
     79 
     80  } 
     81 
     82  # At this stage, the driver has exhausted its collection of links 
     83  # to visit.  Let's say we want to add the URL "http://www.mitre.org" 
     84  # to the driver's list. 
     85  $browser->{links_to_visit}->{'http://www.mitre.org'} = 1; 
     86 
     87  # Now, drive the browser for one iteration. 
     88  $browser->drive(); 
     89   
     90  # Or, we can specify the URL as an argument. 
     91  $browser->drive(url => "http://www.mitre.org"); 
     92 
     93=head1 DESCRIPTION 
     94 
     95This library allows the Agent module to drive an instance of Mozilla 
     96Firefox inside the HoneyClient VM.  The purpose of this module is to 
     97programmatically navigate this browser to different websites, in order to 
     98become purposefully infected with new malware. 
     99 
     100This module is object-oriented in design, retaining all state information 
     101within itself for easy access.  This specific browser implementation inherits 
     102all code from the HoneyClient::Agent::Driver::Browser package. 
     103 
     104Fundamentally, the FF driver is initialized with a set of absolute URLs 
     105for the browser to drive to.  Upon visiting each URL, the driver collects 
     106any B<new> links found and will attempt to drive the browser to each 
     107valid URL upon subsequent iterations of work. 
     108 
     109For each top-level URL given, the driver will attempt to process all 
     110corresponding links that are hosted on the same server, in order to 
     111simulate a complete 'spider' of each server.   
     112 
     113URLs are added and removed from hashtables, as keys.  For each URL, a 
     114calculated "priority" (a positive integer) of the URL is assigned the 
     115value.  When the FF driver is ready to go to a new link, it will always go 
     116to the next link that has the highest priority.  If two URLs have the same 
     117priority, then the FF driver will chose among those two at random. 
     118 
     119Furthermore, the FF driver will try to visit all links shared by a 
     120common server in order before moving on to drive to other, 
     121external links in an ordered fashion.  B<However>, the FF driver may end 
     122up re-visiting old sites, if new links were found that the 
     123FF driver has not visited yet.  
     124 
     125As the FF driver navigates the browser to each link, it 
     126maintains a set of hashtables that record when valid links were 
     127visited (see L<links_visited>); when invalid links were found 
     128(see L<links_ignored>); and when the browser attempted to visit 
     129a link but the operation timed out (see L<links_timed_out>). 
     130By maintaining this internal history, the driver will B<never> 
     131navigate the browser to the same link twice. 
     132 
     133Lastly, it is highly recommended that for each driver B<$object>, 
     134one should call $object->isFinished() prior to making a subsequent 
     135call to $object->drive(), in order to verify that the driver has 
     136not exhausted its set of links to visit.  Otherwise, if 
     137$object->drive() is called with an empty set of links to visit, 
     138the corresponding operation will B<croak>. 
     139 
     140=cut 
    31141 
    32142package HoneyClient::Agent::Driver::Browser::FF; 
    33143 
    34 # XXX: Disabled version check, Honeywall does not have Perl v5.8 installed. 
    35 #use 5.008006; 
    36144use strict; 
    37145use warnings; 
    38 use Config; 
    39146use Carp (); 
    40147 
     
    71178    # Do not simply export all your public functions/methods/constants. 
    72179 
    73     # This allows declaration use HoneyClient::Agent::Driver::Browser::IE ':all'; 
     180    # This allows declaration use HoneyClient::Agent::Driver::Browser::FF ':all'; 
    74181    # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK 
    75182    # will save memory. 
     
    84191    @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); 
    85192 
    86 # XXX: Fix this! 
    87 # Check to make sure our OS is Windows-based. 
    88 #if ($Config{osname} !~ /^MSWin32$/) { 
    89 #    Carp::croak "Error: " . __PACKAGE__ . " will only run on Win32 platforms!\n"; 
    90 #} 
    91  
    92193    $SIG{PIPE} = 'IGNORE';    # Do not exit on broken pipes. 
    93194} 
    94195our ( @EXPORT_OK, $VERSION ); 
    95196 
    96 #TODO: Rewrite the test module 
    97  
    98197=pod 
    99198 
    100199=begin testing 
    101200 
     201# Make sure Log::Log4perl loads 
     202BEGIN { use_ok('Log::Log4perl', qw(:nowarn)) 
     203        or diag("Can't load Log::Log4perl package. Check to make sure the package library is correctly listed within the path."); 
     204        
     205        # Suppress all logging messages, since we need clean output for unit testing. 
     206        Log::Log4perl->init({ 
     207            "log4perl.rootLogger"                               => "DEBUG, Buffer", 
     208            "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer", 
     209            "log4perl.appender.Buffer.min_level"                => "fatal", 
     210            "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout", 
     211            "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", 
     212        }); 
     213} 
     214require_ok('Log::Log4perl'); 
     215use Log::Log4perl qw(:easy); 
     216 
     217# Make sure HoneyClient::Util::Config loads. 
     218BEGIN { use_ok('HoneyClient::Util::Config', qw(getVar)) 
     219        or diag("Can't load HoneyClient::Util::Config package.  Check to make sure the package library is correctly listed within the path.");  
     220 
     221        # Suppress all logging messages, since we need clean output for unit testing. 
     222        Log::Log4perl->init({ 
     223            "log4perl.rootLogger"                               => "DEBUG, Buffer", 
     224            "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer", 
     225            "log4perl.appender.Buffer.min_level"                => "fatal", 
     226            "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout", 
     227            "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", 
     228        }); 
     229         
     230} 
     231require_ok('HoneyClient::Util::Config'); 
     232can_ok('HoneyClient::Util::Config', 'getVar'); 
     233use HoneyClient::Util::Config qw(getVar); 
     234 
     235# Make sure the module loads properly, with the exportable 
     236# functions shared. 
     237BEGIN { use_ok('HoneyClient::Agent::Driver::Browser::FF') or diag("Can't load HoneyClient::Agent::Driver::Browser::FF package.  Check to make sure the package library is correctly listed within the path."); } 
     238require_ok('HoneyClient::Agent::Driver::Browser::FF'); 
     239can_ok('HoneyClient::Agent::Driver::Browser::FF', 'new'); 
     240can_ok('HoneyClient::Agent::Driver::Browser::FF', 'drive'); 
     241can_ok('HoneyClient::Agent::Driver::Browser::FF', 'isFinished'); 
     242can_ok('HoneyClient::Agent::Driver::Browser::FF', 'next'); 
     243can_ok('HoneyClient::Agent::Driver::Browser::FF', 'status'); 
     244can_ok('HoneyClient::Agent::Driver::Browser::FF', 'getNextLink'); 
     245use HoneyClient::Agent::Driver::Browser::FF; 
     246 
     247# Suppress all logging messages, since we need clean output for unit testing. 
     248Log::Log4perl->init({ 
     249    "log4perl.rootLogger"                               => "DEBUG, Buffer", 
     250    "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer", 
     251    "log4perl.appender.Buffer.min_level"                => "fatal", 
     252    "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout", 
     253    "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", 
     254}); 
     255 
     256# Make sure Win32::Job loads. 
     257BEGIN { use_ok('Win32::Job') or diag("Can't load Win32::Job package.  Check to make sure the package library is correctly listed within the path."); } 
     258require_ok('Win32::Job'); 
     259use Win32::Job; 
     260 
     261# Make sure ExtUtils::MakeMaker loads. 
     262BEGIN { use_ok('ExtUtils::MakeMaker', qw(prompt)) or diag("Can't load ExtUtils::MakeMaker package.  Check to make sure the package library is correctly listed within the path."); } 
     263require_ok('ExtUtils::MakeMaker'); 
     264can_ok('ExtUtils::MakeMaker', 'prompt'); 
     265use ExtUtils::MakeMaker qw(prompt); 
     266 
    102267=end testing 
    103268 
     
    105270 
    106271####################################################################### 
    107  
    108 #TODO: Remove any of these use statements that aren't needed 
    109272 
    110273# Include the Global Configuration Processing Library 
    111274use HoneyClient::Util::Config qw(getVar); 
    112275 
    113 # Use ISO 8601 DateTime Libraries 
    114 use DateTime::HiRes; 
    115  
    116 # Use fractional second sleeping. 
    117 # TODO: Need unit testing. 
    118 use Time::HiRes qw(sleep); 
    119  
    120 # Use Storable Library 
    121 use Storable qw(dclone); 
    122  
    123 # Use threads Library 
    124 # TODO: Need unit testing. 
    125 use threads; 
    126  
    127 # TODO: Need unit testing. 
    128 use threads::shared; 
    129  
    130 # TODO: Need unit testing. 
    131 use HoneyClient::Util::SOAP qw(getClientHandle); 
    132  
    133 # TODO: Need unit testing. 
     276# Include Win32 Job Library 
    134277use Win32::Job; 
    135278 
     
    140283our $LOG = get_logger(); 
    141284 
    142 # TODO: clean this up. 
    143 #my %PARAMS = ( 
    144 #); 
    145  
    146 ####################################################################### 
    147 # Private Methods Implemented                                         # 
    148 ####################################################################### 
    149  
    150 #sub new { 
    151 #    
    152 #    # - This function takes in an optional hashtable, 
    153 #    #   that contains various key => 'value' configuration 
    154 #    #   parameters. 
    155 #    # 
    156 #    # - For each parameter given, it overwrites any corresponding 
    157 #    #   parameters specified within the default hashtable, %PARAMS, 
    158 #    #   with custom entries that were given as parameters. 
    159 #    # 
    160 #    # - Finally, it returns a blessed instance of the 
    161 #    #   merged hashtable, as an 'object'. 
    162 
    163 #    # Get the class name. 
    164 #    my $self = shift; 
    165 
    166 #    # Get the rest of the arguments, as a hashtable. 
    167 #    # Hash-based arguments are used, since HoneyClient::Util::SOAP is unable to handle 
    168 #    # hash references directly.  Thus, flat hashtables are used throughout the code 
    169 #    # for consistency. 
    170 #    my %args = @_; 
    171 
    172 #    # Check to see if the class name is inherited or defined. 
    173 #    my $class = ref($self) || $self; 
    174 
    175 #    # Initialize default parameters. 
    176 #    my %params = %{dclone(\%PARAMS)}; 
    177 #    $self = $class->SUPER::new(); 
    178 #    @{$self}{keys %params} = values %params; 
    179 
    180 #    # Now, overwrite any default parameters that were redefined 
    181 #    # in the supplied arguments. 
    182 #    @{$self}{keys %args} = values %args; 
    183 
    184 #    # Now, assign our object the appropriate namespace. 
    185 #    bless $self, $class; 
    186 
    187 #    # Finally, return the blessed object. 
    188 #    return $self; 
    189 #} 
     285####################################################################### 
     286# Public Methods Implemented                                          # 
     287####################################################################### 
     288 
     289=pod 
     290 
     291=head1 METHODS OVERRIDDEN 
     292 
     293The following functions have been overridden by the FF driver.  All other 
     294methods were implemented by the generic Browser driver.  For further 
     295information about the Browser driver, see the L<HoneyClient::Agent::Driver::Browser> 
     296documentation. 
     297 
     298=head2 $object->drive(url => $url) 
     299 
     300=over 4 
     301 
     302Drives an instance of Mozilla Firefox for one iteration, 
     303navigating either to the specified URL or to the next URL computed within 
     304the Browser driver's internal hashtables. 
     305 
     306For a description of which hashtable is consulted upon each iteration of 
     307drive(), see the B<next_link_to_visit> description of the  
     308L<HoneyClient::Agent::Driver::Browser> documentation, in the 
     309"DEFAULT PARAMETER LIST" section. 
     310 
     311Once a drive() iternation has completed, the corresponding browser process 
     312is terminated.  Thus, each call to drive() invokes a new instance of the 
     313browser. 
     314 
     315I<Inputs>: 
     316 B<$url> is an optional argument, specifying the next immediate URL the browser 
     317must drive to. 
     318 
     319I<Output>: The updated FF driver B<$object>, containing state information from driving the 
     320browser for one iteration. 
     321 
     322B<Warning>: This method will B<croak>, if the FF driver object is B<unable> 
     323to navigate to a new link, because its list of links to vist is empty and no new 
     324URL was supplied. 
     325 
     326=back 
     327 
     328=begin testing 
     329 
     330# Generate a notice, to clarify our assumptions. 
     331diag(""); 
     332diag("About to run basic FF-specific browser tests."); 
     333diag("Note: These tests *require* network connectivity and"); 
     334diag("*expect* FF to be installed at the following location."); 
     335diag(""); 
     336 
     337my $processExec = getVar(name      => "process_exec", 
     338                         namespace => "HoneyClient::Agent::Driver::Browser::FF"); 
     339my $processName = getVar(name      => "process_name", 
     340                         namespace => "HoneyClient::Agent::Driver::Browser::FF"); 
     341 
     342diag("Process Name:\t\t'" . $processName . "'"); 
     343diag("Process Location:\t'" . $processExec . "'"); 
     344diag(""); 
     345diag("If FF is installed in a different location or has a different executable name,"); 
     346diag("then please answer *NO* to the next question and update your etc/honeyclient.xml"); 
     347diag("file, changing the 'process_name' and 'process_exec' elements in the"); 
     348diag("<HoneyClient/><Agent/><Driver/><Browser/><FF/> section."); 
     349diag(""); 
     350diag("Then, once updated, re-run these tests."); 
     351diag(""); 
     352 
     353my $question; 
     354$question = prompt("# Do you want to run these tests?", "yes"); 
     355if ($question !~ /^y.*/i) { 
     356    exit; 
     357
     358 
     359my $ie = HoneyClient::Agent::Driver::Browser::FF->new(test => 1); 
     360is($ie->{test}, 1, "new(test => 1)") or diag("The new() call failed."); 
     361isa_ok($ie, 'HoneyClient::Agent::Driver::Browser::FF', "new(test => 1)") or diag("The new() call failed."); 
     362 
     363diag(""); 
     364diag("About to drive FF to a specific website for *exactly* " . $ie->{timeout} . " seconds."); 
     365diag("Note: Please do *NOT* close the browser manually; the test code should close it automatically."); 
     366diag(""); 
     367 
     368$question = prompt("# Which website should FF browse to?", "http://www.google.com"); 
     369$ie->drive(url => $question); 
     370 
     371diag(""); 
     372$question = prompt("# Did FF properly render the page and automatically exit?", "yes"); 
     373if ($question !~ /^y.*/i) { 
     374    diag(""); 
     375    diag("Check your network connectivity and verify that you can manually browse this page in FF."); 
     376    diag("Then, re-run these tests."); 
     377    diag(""); 
     378    diag("If the tests still do not work, please submit a ticket to:"); 
     379    diag("http://www.honeyclient.org/trac/newticket"); 
     380    diag(""); 
     381    fail("The drive() call failed."); 
     382
     383 
     384=end testing 
     385 
     386=cut 
    190387 
    191388sub drive { 
     
    212409    } 
    213410 
    214     # Drive the generic browser before opening with IE 
     411    # Drive the generic browser before opening with FF 
    215412    $self = $self->SUPER::drive(%args); 
    216  
     413     
    217414    # Sanity check: Make sure our next URL is defined. 
    218415    unless (defined($args{'url'})) { 
     
    230427    # Sanity check. 
    231428    if (!defined($job)) { 
    232         $LOG->error("Error: Unable to spawn new job - " . $^E . "."); 
    233         Carp::croak "Error: Unable to spawn new job - " . $^E . ".\n"; 
     429        $LOG->error("Error: Unable to spawn a new process - " . $^E . "."); 
     430        Carp::croak "Error: Unable to spawn a new process - " . $^E . ".\n"; 
    234431    } 
    235432 
    236433    # Spawn the job. 
    237     $job->spawn(undef, "\"C:\\Program Files\\Mozilla Firefox\\firefox.exe\"" . $args{'url'}); 
    238  
    239     # TODO: check to see if spawn fails. 
     434    my $processExec = getVar(name => "process_exec"); 
     435    my $processName = getVar(name => "process_name"); 
     436    my $status = $job->spawn($processExec, $processName . " " . $args{'url'}); 
     437 
     438    # Sanity check. 
     439    if (!defined($status)) { 
     440        $LOG->error("Error: Unable to spawn a new browser - " . $^E . "."); 
     441        Carp::croak "Error: Unable to spawn a new browser - " . $^E . ".\n"; 
     442    } 
    240443 
    241444    # Run the job. 
    242445    $job->run($timeout); 
    243446 
    244     # TODO: check to see if run fails. 
     447    # Check to see if run fails. 
     448    $status = $job->status(); 
     449 
     450    # Sanity check. 
     451    if (!defined($status) || 
     452        !scalar(%{$status})) { 
     453        $LOG->error("Error: Unable to retrieve job status from spawned process."); 
     454        Carp::croak "Error: Unable to retrieve job status from spawned process.\n"; 
     455    } 
     456 
     457    # Figure out the correct Process ID. 
     458    my @keys = keys(%{$status}); 
     459    my $processID = pop(@keys); 
     460 
     461    # Sanity checks. 
     462    if (!defined($processID) || 
     463        !exists($status->{$processID}->{'exitcode'}) || 
     464        !defined($status->{$processID}->{'exitcode'})) { 
     465        $LOG->error("Error: Unable to retrieve job status from spawned process."); 
     466        Carp::croak "Error: Unable to retrieve job status from spawned process.\n"; 
     467    } 
     468 
     469    # TODO: We may want to report this suspicious activity back to the Agent; 
     470    # perhaps force the Agent to do an early integrity check, to make sure nothing 
     471    # sketchy is going on. 
     472 
     473    # Check to make sure the exitcode is '293', meaning, that the 
     474    # application didn't unexpectedly die early. 
     475    if ($status->{$processID}->{'exitcode'} != 293) { 
     476        $LOG->warn("Unexpected: '" . $processName . "' process (ID = " . $processID . ") terminated early!"); 
     477    } 
    245478 
    246479    # Return the modified object state. 
     
    251484 
    2524851; 
     486 
     487####################################################################### 
     488# Additional Module Documentation                                     # 
     489####################################################################### 
     490 
     491__END__ 
     492 
     493=head1 BUGS & ASSUMPTIONS 
     494 
     495This package will only run on Win32 platforms.  Furthermore, it has 
     496only been tested to work reliably within a Cygwin environment. 
     497 
     498In a nutshell, this object is nothing more than a blessed anonymous 
     499reference to a hashtable, where (key => value) pairs are defined in 
     500the L<DEFAULT PARAMETER LIST>, as well as fed via the new() function 
     501during object initialization.  As such, this package does B<not> 
     502perform any rigorous B<data validation> prior to accepting any new 
     503or overriding (key => value) pairs. 
     504 
     505However, additional links can be fed to any FF driver at any time, by 
     506simply adding new hashtable entries to the B<links_to_visit> hashtable 
     507within the B<$object>. 
     508 
     509For example, if you wanted to add the URL "http://www.mitre.org" 
     510to the FF driver B<$object>, simply use the following code: 
     511 
     512  $object->{links_to_visit}->{'http://www.mitre.org'} = 1; 
     513 
     514In general, the FF driver does B<not> know how many links it will 
     515ultimately end up browsing to, until it conducts an exhaustive 
     516spider of all initial URLs supplied.  As such, expect the output 
     517of $object->status() to change significantly, upon each 
     518$object->drive() iteration. 
     519 
     520For example, if at one given point, the status of B<percent_complete> 
     521is 30% and then this value drops to 15% upon another iteration, then 
     522this means that the total number of links to drive to has greatly 
     523increased. 
     524 
     525Lastly, we assume that the Mozilla Firefox browser has 
     526been preconfigured to B<not cache any data>.  This ensures the browser 
     527will render the most recent version of the content hosted at each URL. 
     528 
     529=head1 SEE ALSO 
     530 
     531L<HoneyClient::Agent::Driver> 
     532 
     533L<HoneyClient::Agent::Driver::Browser> 
     534 
     535L<HoneyClient::Agent::Driver::Browser::IE> 
     536 
     537L<http://www.honeyclient.org/trac> 
     538 
     539=head1 REPORTING BUGS 
     540 
     541L<http://www.honeyclient.org/trac/newticket> 
     542 
     543=head1 AUTHORS 
     544 
     545Kathy Wang, E<lt>knwang@mitre.orgE<gt> 
     546 
     547Thanh Truong, E<lt>ttruong@mitre.orgE<gt> 
     548 
     549Darien Kindlund, E<lt>kindlund@mitre.orgE<gt> 
     550 
     551Brad Stephenson, E<lt>stephenson@mitre.orgE<gt> 
     552 
     553=head1 COPYRIGHT & LICENSE 
     554 
     555Copyright (C) 2007 The MITRE Corporation.  All rights reserved. 
     556 
     557This program is free software; you can redistribute it and/or 
     558modify it under the terms of the GNU General Public License 
     559as published by the Free Software Foundation, using version 2 
     560of the License. 
     561 
     562This program is distributed in the hope that it will be useful, 
     563but WITHOUT ANY WARRANTY; without even the implied warranty of 
     564MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     565GNU General Public License for more details. 
     566 
     567You should have received a copy of the GNU General Public License 
     568along with this program; if not, write to the Free Software 
     569Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
     57002110-1301, USA. 
     571 
     572 
     573=cut 
     574 
  • honeyclient/branches/exp/kindlund-firefox/t/honeyclient_agent_driver_browser_ff.t

    r725 r742  
    77 
    88 
     9# =begin testing 
     10{ 
     11# Make sure Log::Log4perl loads 
     12BEGIN { use_ok('Log::Log4perl', qw(:nowarn)) 
     13        or diag("Can't load Log::Log4perl package. Check to make sure the package library is correctly listed within the path."); 
     14        
     15        # Suppress all logging messages, since we need clean output for unit testing. 
     16        Log::Log4perl->init({ 
     17            "log4perl.rootLogger"                               => "DEBUG, Buffer", 
     18            "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer", 
     19            "log4perl.appender.Buffer.min_level"                => "fatal", 
     20            "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout", 
     21            "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", 
     22        }); 
     23} 
     24require_ok('Log::Log4perl'); 
     25use Log::Log4perl qw(:easy); 
     26 
     27# Make sure HoneyClient::Util::Config loads. 
     28BEGIN { use_ok('HoneyClient::Util::Config', qw(getVar)) 
     29        or diag("Can't load HoneyClient::Util::Config package.  Check to make sure the package library is correctly listed within the path.");  
     30 
     31        # Suppress all logging messages, since we need clean output for unit testing. 
     32        Log::Log4perl->init({ 
     33            "log4perl.rootLogger"                               => "DEBUG, Buffer", 
     34            "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer", 
     35            "log4perl.appender.Buffer.min_level"                => "fatal", 
     36            "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout", 
     37            "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", 
     38        }); 
     39         
     40} 
     41require_ok('HoneyClient::Util::Config'); 
     42can_ok('HoneyClient::Util::Config', 'getVar'); 
     43use HoneyClient::Util::Config qw(getVar); 
     44 
     45# Make sure the module loads properly, with the exportable 
     46# functions shared. 
     47BEGIN { use_ok('HoneyClient::Agent::Driver::Browser::FF') or diag("Can't load HoneyClient::Agent::Driver::Browser::FF package.  Check to make sure the package library is correctly listed within the path."); } 
     48require_ok('HoneyClient::Agent::Driver::Browser::FF'); 
     49can_ok('HoneyClient::Agent::Driver::Browser::FF', 'new'); 
     50can_ok('HoneyClient::Agent::Driver::Browser::FF', 'drive'); 
     51can_ok('HoneyClient::Agent::Driver::Browser::FF', 'isFinished'); 
     52can_ok('HoneyClient::Agent::Driver::Browser::FF', 'next'); 
     53can_ok('HoneyClient::Agent::Driver::Browser::FF', 'status'); 
     54can_ok('HoneyClient::Agent::Driver::Browser::FF', 'getNextLink'); 
     55use HoneyClient::Agent::Driver::Browser::FF; 
     56 
     57# Suppress all logging messages, since we need clean output for unit testing. 
     58Log::Log4perl->init({ 
     59    "log4perl.rootLogger"                               => "DEBUG, Buffer", 
     60    "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer", 
     61    "log4perl.appender.Buffer.min_level"                => "fatal", 
     62    "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout", 
     63    "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", 
     64}); 
     65 
     66# Make sure Win32::Job loads. 
     67BEGIN { use_ok('Win32::Job') or diag("Can't load Win32::Job package.  Check to make sure the package library is correctly listed within the path."); } 
     68require_ok('Win32::Job'); 
     69use Win32::Job; 
     70 
     71# Make sure ExtUtils::MakeMaker loads. 
     72BEGIN { use_ok('ExtUtils::MakeMaker', qw(prompt)) or diag("Can't load ExtUtils::MakeMaker package.  Check to make sure the package library is correctly listed within the path."); } 
     73require_ok('ExtUtils::MakeMaker'); 
     74can_ok('ExtUtils::MakeMaker', 'prompt'); 
     75use ExtUtils::MakeMaker qw(prompt); 
     76} 
     77 
     78 
     79 
     80# =begin testing 
     81{ 
     82# Generate a notice, to clarify our assumptions. 
     83diag(""); 
     84diag("About to run basic FF-specific browser tests."); 
     85diag("Note: These tests *require* network connectivity and"); 
     86diag("*expect* FF to be installed at the following location."); 
     87diag(""); 
     88 
     89my $processExec = getVar(name      => "process_exec", 
     90                         namespace => "HoneyClient::Agent::Driver::Browser::FF"); 
     91my $processName = getVar(name      => "process_name", 
     92                         namespace => "HoneyClient::Agent::Driver::Browser::FF"); 
     93 
     94diag("Process Name:\t\t'" . $processName . "'"); 
     95diag("Process Location:\t'" . $processExec . "'"); 
     96diag(""); 
     97diag("If FF is installed in a different location or has a different executable name,"); 
     98diag("then please answer *NO* to the next question and update your etc/honeyclient.xml"); 
     99diag("file, changing the 'process_name' and 'process_exec' elements in the"); 
     100diag("<HoneyClient/><Agent/><Driver/><Browser/><FF/> section."); 
     101diag(""); 
     102diag("Then, once updated, re-run these tests."); 
     103diag(""); 
     104 
     105my $question; 
     106$question = prompt("# Do you want to run these tests?", "yes"); 
     107if ($question !~ /^y.*/i) { 
     108    exit; 
     109} 
     110 
     111my $ie = HoneyClient::Agent::Driver::Browser::FF->new(test => 1); 
     112is($ie->{test}, 1, "new(test => 1)") or diag("The new() call failed."); 
     113isa_ok($ie, 'HoneyClient::Agent::Driver::Browser::FF', "new(test => 1)") or diag("The new() call failed."); 
     114 
     115diag(""); 
     116diag("About to drive FF to a specific website for *exactly* " . $ie->{timeout} . " seconds."); 
     117diag("Note: Please do *NOT* close the browser manually; the test code should close it automatically."); 
     118diag(""); 
     119 
     120$question = prompt("# Which website should FF browse to?", "http://www.google.com"); 
     121$ie->drive(url => $question); 
     122 
     123diag(""); 
     124$question = prompt("# Did FF properly render the page and automatically exit?", "yes"); 
     125if ($question !~ /^y.*/i) { 
     126    diag(""); 
     127    diag("Check your network connectivity and verify that you can manually browse this page in FF."); 
     128    diag("Then, re-run these tests."); 
     129    diag(""); 
     130    diag("If the tests still do not work, please submit a ticket to:"); 
     131    diag("http://www.honeyclient.org/trac/newticket"); 
     132    diag(""); 
     133    fail("The drive() call failed."); 
     134} 
     135} 
    9136 
    10137