Changeset 742
- Timestamp:
- 07/23/07 16:45:04 (1 year ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
honeyclient/branches/exp/kindlund-firefox/lib/HoneyClient/Agent/Driver/Browser/FF.pm
r723 r742 1 ####################################################################### ########1 ####################################################################### 2 2 # Created on: May 11, 2006 3 3 # Package: HoneyClient::Agent::Driver::FF … … 9 9 # CVS: $Id$ 10 10 # 11 # @author knwang, xkovah, kindlund, ttruong11 # @author knwang, ttruong, kindlund, stephenson 12 12 # 13 13 # Copyright (C) 2007 The MITRE Corporation. All rights reserved. … … 28 28 # 02110-1301, USA. 29 29 # 30 ############################################################################### 30 # 31 ####################################################################### 32 33 =pod 34 35 =head1 NAME 36 37 HoneyClient::Agent::Driver::Browser::FF - Perl extension to drive Mozilla 38 Firefox to a given web page. This package extends the 39 HoneyClient::Agent::Driver::Browser package, by overridding the drive() method. 40 41 =head1 VERSION 42 43 This 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 95 This library allows the Agent module to drive an instance of Mozilla 96 Firefox inside the HoneyClient VM. The purpose of this module is to 97 programmatically navigate this browser to different websites, in order to 98 become purposefully infected with new malware. 99 100 This module is object-oriented in design, retaining all state information 101 within itself for easy access. This specific browser implementation inherits 102 all code from the HoneyClient::Agent::Driver::Browser package. 103 104 Fundamentally, the FF driver is initialized with a set of absolute URLs 105 for the browser to drive to. Upon visiting each URL, the driver collects 106 any B<new> links found and will attempt to drive the browser to each 107 valid URL upon subsequent iterations of work. 108 109 For each top-level URL given, the driver will attempt to process all 110 corresponding links that are hosted on the same server, in order to 111 simulate a complete 'spider' of each server. 112 113 URLs are added and removed from hashtables, as keys. For each URL, a 114 calculated "priority" (a positive integer) of the URL is assigned the 115 value. When the FF driver is ready to go to a new link, it will always go 116 to the next link that has the highest priority. If two URLs have the same 117 priority, then the FF driver will chose among those two at random. 118 119 Furthermore, the FF driver will try to visit all links shared by a 120 common server in order before moving on to drive to other, 121 external links in an ordered fashion. B<However>, the FF driver may end 122 up re-visiting old sites, if new links were found that the 123 FF driver has not visited yet. 124 125 As the FF driver navigates the browser to each link, it 126 maintains a set of hashtables that record when valid links were 127 visited (see L<links_visited>); when invalid links were found 128 (see L<links_ignored>); and when the browser attempted to visit 129 a link but the operation timed out (see L<links_timed_out>). 130 By maintaining this internal history, the driver will B<never> 131 navigate the browser to the same link twice. 132 133 Lastly, it is highly recommended that for each driver B<$object>, 134 one should call $object->isFinished() prior to making a subsequent 135 call to $object->drive(), in order to verify that the driver has 136 not exhausted its set of links to visit. Otherwise, if 137 $object->drive() is called with an empty set of links to visit, 138 the corresponding operation will B<croak>. 139 140 =cut 31 141 32 142 package HoneyClient::Agent::Driver::Browser::FF; 33 143 34 # XXX: Disabled version check, Honeywall does not have Perl v5.8 installed.35 #use 5.008006;36 144 use strict; 37 145 use warnings; 38 use Config;39 146 use Carp (); 40 147 … … 71 178 # Do not simply export all your public functions/methods/constants. 72 179 73 # This allows declaration use HoneyClient::Agent::Driver::Browser:: IE':all';180 # This allows declaration use HoneyClient::Agent::Driver::Browser::FF ':all'; 74 181 # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK 75 182 # will save memory. … … 84 191 @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); 85 192 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 92 193 $SIG{PIPE} = 'IGNORE'; # Do not exit on broken pipes. 93 194 } 94 195 our ( @EXPORT_OK, $VERSION ); 95 196 96 #TODO: Rewrite the test module97 98 197 =pod 99 198 100 199 =begin testing 101 200 201 # Make sure Log::Log4perl loads 202 BEGIN { 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 } 214 require_ok('Log::Log4perl'); 215 use Log::Log4perl qw(:easy); 216 217 # Make sure HoneyClient::Util::Config loads. 218 BEGIN { 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 } 231 require_ok('HoneyClient::Util::Config'); 232 can_ok('HoneyClient::Util::Config', 'getVar'); 233 use HoneyClient::Util::Config qw(getVar); 234 235 # Make sure the module loads properly, with the exportable 236 # functions shared. 237 BEGIN { 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."); } 238 require_ok('HoneyClient::Agent::Driver::Browser::FF'); 239 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'new'); 240 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'drive'); 241 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'isFinished'); 242 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'next'); 243 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'status'); 244 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'getNextLink'); 245 use HoneyClient::Agent::Driver::Browser::FF; 246 247 # Suppress all logging messages, since we need clean output for unit testing. 248 Log::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. 257 BEGIN { 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."); } 258 require_ok('Win32::Job'); 259 use Win32::Job; 260 261 # Make sure ExtUtils::MakeMaker loads. 262 BEGIN { 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."); } 263 require_ok('ExtUtils::MakeMaker'); 264 can_ok('ExtUtils::MakeMaker', 'prompt'); 265 use ExtUtils::MakeMaker qw(prompt); 266 102 267 =end testing 103 268 … … 105 270 106 271 ####################################################################### 107 108 #TODO: Remove any of these use statements that aren't needed109 272 110 273 # Include the Global Configuration Processing Library 111 274 use HoneyClient::Util::Config qw(getVar); 112 275 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 134 277 use Win32::Job; 135 278 … … 140 283 our $LOG = get_logger(); 141 284 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 293 The following functions have been overridden by the FF driver. All other 294 methods were implemented by the generic Browser driver. For further 295 information about the Browser driver, see the L<HoneyClient::Agent::Driver::Browser> 296 documentation. 297 298 =head2 $object->drive(url => $url) 299 300 =over 4 301 302 Drives an instance of Mozilla Firefox for one iteration, 303 navigating either to the specified URL or to the next URL computed within 304 the Browser driver's internal hashtables. 305 306 For a description of which hashtable is consulted upon each iteration of 307 drive(), see the B<next_link_to_visit> description of the 308 L<HoneyClient::Agent::Driver::Browser> documentation, in the 309 "DEFAULT PARAMETER LIST" section. 310 311 Once a drive() iternation has completed, the corresponding browser process 312 is terminated. Thus, each call to drive() invokes a new instance of the 313 browser. 314 315 I<Inputs>: 316 B<$url> is an optional argument, specifying the next immediate URL the browser 317 must drive to. 318 319 I<Output>: The updated FF driver B<$object>, containing state information from driving the 320 browser for one iteration. 321 322 B<Warning>: This method will B<croak>, if the FF driver object is B<unable> 323 to navigate to a new link, because its list of links to vist is empty and no new 324 URL was supplied. 325 326 =back 327 328 =begin testing 329 330 # Generate a notice, to clarify our assumptions. 331 diag(""); 332 diag("About to run basic FF-specific browser tests."); 333 diag("Note: These tests *require* network connectivity and"); 334 diag("*expect* FF to be installed at the following location."); 335 diag(""); 336 337 my $processExec = getVar(name => "process_exec", 338 namespace => "HoneyClient::Agent::Driver::Browser::FF"); 339 my $processName = getVar(name => "process_name", 340 namespace => "HoneyClient::Agent::Driver::Browser::FF"); 341 342 diag("Process Name:\t\t'" . $processName . "'"); 343 diag("Process Location:\t'" . $processExec . "'"); 344 diag(""); 345 diag("If FF is installed in a different location or has a different executable name,"); 346 diag("then please answer *NO* to the next question and update your etc/honeyclient.xml"); 347 diag("file, changing the 'process_name' and 'process_exec' elements in the"); 348 diag("<HoneyClient/><Agent/><Driver/><Browser/><FF/> section."); 349 diag(""); 350 diag("Then, once updated, re-run these tests."); 351 diag(""); 352 353 my $question; 354 $question = prompt("# Do you want to run these tests?", "yes"); 355 if ($question !~ /^y.*/i) { 356 exit; 357 } 358 359 my $ie = HoneyClient::Agent::Driver::Browser::FF->new(test => 1); 360 is($ie->{test}, 1, "new(test => 1)") or diag("The new() call failed."); 361 isa_ok($ie, 'HoneyClient::Agent::Driver::Browser::FF', "new(test => 1)") or diag("The new() call failed."); 362 363 diag(""); 364 diag("About to drive FF to a specific website for *exactly* " . $ie->{timeout} . " seconds."); 365 diag("Note: Please do *NOT* close the browser manually; the test code should close it automatically."); 366 diag(""); 367 368 $question = prompt("# Which website should FF browse to?", "http://www.google.com"); 369 $ie->drive(url => $question); 370 371 diag(""); 372 $question = prompt("# Did FF properly render the page and automatically exit?", "yes"); 373 if ($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 190 387 191 388 sub drive { … … 212 409 } 213 410 214 # Drive the generic browser before opening with IE411 # Drive the generic browser before opening with FF 215 412 $self = $self->SUPER::drive(%args); 216 413 217 414 # Sanity check: Make sure our next URL is defined. 218 415 unless (defined($args{'url'})) { … … 230 427 # Sanity check. 231 428 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"; 234 431 } 235 432 236 433 # 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 } 240 443 241 444 # Run the job. 242 445 $job->run($timeout); 243 446 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 } 245 478 246 479 # Return the modified object state. … … 251 484 252 485 1; 486 487 ####################################################################### 488 # Additional Module Documentation # 489 ####################################################################### 490 491 __END__ 492 493 =head1 BUGS & ASSUMPTIONS 494 495 This package will only run on Win32 platforms. Furthermore, it has 496 only been tested to work reliably within a Cygwin environment. 497 498 In a nutshell, this object is nothing more than a blessed anonymous 499 reference to a hashtable, where (key => value) pairs are defined in 500 the L<DEFAULT PARAMETER LIST>, as well as fed via the new() function 501 during object initialization. As such, this package does B<not> 502 perform any rigorous B<data validation> prior to accepting any new 503 or overriding (key => value) pairs. 504 505 However, additional links can be fed to any FF driver at any time, by 506 simply adding new hashtable entries to the B<links_to_visit> hashtable 507 within the B<$object>. 508 509 For example, if you wanted to add the URL "http://www.mitre.org" 510 to the FF driver B<$object>, simply use the following code: 511 512 $object->{links_to_visit}->{'http://www.mitre.org'} = 1; 513 514 In general, the FF driver does B<not> know how many links it will 515 ultimately end up browsing to, until it conducts an exhaustive 516 spider of all initial URLs supplied. As such, expect the output 517 of $object->status() to change significantly, upon each 518 $object->drive() iteration. 519 520 For example, if at one given point, the status of B<percent_complete> 521 is 30% and then this value drops to 15% upon another iteration, then 522 this means that the total number of links to drive to has greatly 523 increased. 524 525 Lastly, we assume that the Mozilla Firefox browser has 526 been preconfigured to B<not cache any data>. This ensures the browser 527 will render the most recent version of the content hosted at each URL. 528 529 =head1 SEE ALSO 530 531 L<HoneyClient::Agent::Driver> 532 533 L<HoneyClient::Agent::Driver::Browser> 534 535 L<HoneyClient::Agent::Driver::Browser::IE> 536 537 L<http://www.honeyclient.org/trac> 538 539 =head1 REPORTING BUGS 540 541 L<http://www.honeyclient.org/trac/newticket> 542 543 =head1 AUTHORS 544 545 Kathy Wang, E<lt>knwang@mitre.orgE<gt> 546 547 Thanh Truong, E<lt>ttruong@mitre.orgE<gt> 548 549 Darien Kindlund, E<lt>kindlund@mitre.orgE<gt> 550 551 Brad Stephenson, E<lt>stephenson@mitre.orgE<gt> 552 553 =head1 COPYRIGHT & LICENSE 554 555 Copyright (C) 2007 The MITRE Corporation. All rights reserved. 556 557 This program is free software; you can redistribute it and/or 558 modify it under the terms of the GNU General Public License 559 as published by the Free Software Foundation, using version 2 560 of the License. 561 562 This program is distributed in the hope that it will be useful, 563 but WITHOUT ANY WARRANTY; without even the implied warranty of 564 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 565 GNU General Public License for more details. 566 567 You should have received a copy of the GNU General Public License 568 along with this program; if not, write to the Free Software 569 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 570 02110-1301, USA. 571 572 573 =cut 574 honeyclient/branches/exp/kindlund-firefox/t/honeyclient_agent_driver_browser_ff.t
r725 r742 7 7 8 8 9 # =begin testing 10 { 11 # Make sure Log::Log4perl loads 12 BEGIN { 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 } 24 require_ok('Log::Log4perl'); 25 use Log::Log4perl qw(:easy); 26 27 # Make sure HoneyClient::Util::Config loads. 28 BEGIN { 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 } 41 require_ok('HoneyClient::Util::Config'); 42 can_ok('HoneyClient::Util::Config', 'getVar'); 43 use HoneyClient::Util::Config qw(getVar); 44 45 # Make sure the module loads properly, with the exportable 46 # functions shared. 47 BEGIN { 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."); } 48 require_ok('HoneyClient::Agent::Driver::Browser::FF'); 49 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'new'); 50 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'drive'); 51 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'isFinished'); 52 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'next'); 53 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'status'); 54 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'getNextLink'); 55 use HoneyClient::Agent::Driver::Browser::FF; 56 57 # Suppress all logging messages, since we need clean output for unit testing. 58 Log::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. 67 BEGIN { 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."); } 68 require_ok('Win32::Job'); 69 use Win32::Job; 70 71 # Make sure ExtUtils::MakeMaker loads. 72 BEGIN { 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."); } 73 require_ok('ExtUtils::MakeMaker'); 74 can_ok('ExtUtils::MakeMaker', 'prompt'); 75 use ExtUtils::MakeMaker qw(prompt); 76 } 77 78 79 80 # =begin testing 81 { 82 # Generate a notice, to clarify our assumptions. 83 diag(""); 84 diag("About to run basic FF-specific browser tests."); 85 diag("Note: These tests *require* network connectivity and"); 86 diag("*expect* FF to be installed at the following location."); 87 diag(""); 88 89 my $processExec = getVar(name => "process_exec", 90 namespace => "HoneyClient::Agent::Driver::Browser::FF"); 91 my $processName = getVar(name => "process_name", 92 namespace => "HoneyClient::Agent::Driver::Browser::FF"); 93 94 diag("Process Name:\t\t'" . $processName . "'"); 95 diag("Process Location:\t'" . $processExec . "'"); 96 diag(""); 97 diag("If FF is installed in a different location or has a different executable name,"); 98 diag("then please answer *NO* to the next question and update your etc/honeyclient.xml"); 99 diag("file, changing the 'process_name' and 'process_exec' elements in the"); 100 diag("<HoneyClient/><Agent/><Driver/><Browser/><FF/> section."); 101 diag(""); 102 diag("Then, once updated, re-run these tests."); 103 diag(""); 104 105 my $question; 106 $question = prompt("# Do you want to run these tests?", "yes"); 107 if ($question !~ /^y.*/i) { 108 exit; 109 } 110 111 my $ie = HoneyClient::Agent::Driver::Browser::FF->new(test => 1); 112 is($ie->{test}, 1, "new(test => 1)") or diag("The new() call failed."); 113 isa_ok($ie, 'HoneyClient::Agent::Driver::Browser::FF', "new(test => 1)") or diag("The new() call failed."); 114 115 diag(""); 116 diag("About to drive FF to a specific website for *exactly* " . $ie->{timeout} . " seconds."); 117 diag("Note: Please do *NOT* close the browser manually; the test code should close it automatically."); 118 diag(""); 119 120 $question = prompt("# Which website should FF browse to?", "http://www.google.com"); 121 $ie->drive(url => $question); 122 123 diag(""); 124 $question = prompt("# Did FF properly render the page and automatically exit?", "yes"); 125 if ($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 } 9 136 10 137
