📄 driver.pl
字号:
#!/usr/bin/perluse strict;use LWP;use HTML::LinkExtor;use URI::URL;use File::Copy;use FileHandle;use Socket;use POSIX qw(ctime);use POSIX qw(mktime);use POSIX qw(strftime);use POSIX qw(ceil);use POSIX ":sys_wait_h";#### Declarations and Initializationmy $CLASS_HOME = "/afs/cs.cmu.edu/academic/class/15213-s02/";my $ASSN_HOME = "$CLASS_HOME/labs/L7/";my $TESTS_HOME = "$ASSN_HOME/tests/";my $PROXY_LOGFILE;my $PROXY_FILTER = "proxy.filter";my $PROXY_FORWARD = "$TESTS_HOME/proxy.forward";my $PROXY_TEST = "proxy.test";my @filter_tests = ();my @forward_tests = ();my $PORT = 3128;my $PWD = `pwd`;my $MYLOG;my $current_time = time;my ($i, @ctests);my %options = ('debug' => 1);my $PID;my $PART1 = 0;my $PART2 = 0;my $correctness_score;my $threading_score;my $cmd;my $testcase;#### Objectsmy $UA = new LWP::UserAgent;my $LE = HTML::LinkExtor->new();$UA->agent("Mozilla/8.0");$UA->timeout(60);#### Print usage informationsub print_usage { die "usage: ./driver.pl [port_number] [proxy-log] [lab-part]\n";}#### Reads an entire file.sub read_file { my $file = shift; my $contents; open MYFILE, "< $file" or return undef; $contents = ""; while (<MYFILE>) { $contents .= $_; } close MYFILE; return $contents;}#### partners()## Returns the Andrew IDs of the two students specified as partners in proxy.c# Also returns the team namesub team { my $dir = shift; my $team = ""; my ($latest_file, $file, $file_contents, $temp, $temp2); $file_contents = read_file("proxy.c"); $temp = index $file_contents, "{", (index $file_contents, "team_struct"); $temp2 = substr $file_contents, $temp + 1, ((index $file_contents, "}", $temp) - $temp - 1); my @struct_lines = split /\n/, $temp2; $temp = 0; foreach $temp2 (@struct_lines) { chomp $temp2; if ($temp2 =~ /\"(.*)\"(,|;)?/) { ++$temp; if ($temp == 2) { $team = $1; } if ($temp == 4) { $team .= "+"; $team .= $1; } } } return $team;}sub gradeof { my ($crashes, $total) = @_; return $total - $crashes;}sub run_proxy { my $x; ### # Remove the logfile unlink $PROXY_LOGFILE; ### # Set up the UA correctly $UA->proxy('http', "http://localhost:$PORT/"); ### # Run the proxy my $pid = fork; return -1 if(!defined $pid); if (!$pid) { print "./proxy $PORT\n"; exec ("./proxy $PORT"); exit 10; } else { # Wait a little while and make sure it didn't crash up front sleep 3; $x = waitpid(-1, &WNOHANG); if ($x == $pid) { print "Oops, proxy crashed! exit this test...\n"; return -1; } } return $pid;}sub parse_test { my $file = shift; my $url; my $method; my @headers = (); open FILE, "< $file"; while (<FILE>) { chomp; last if($_ eq ""); if ($_ =~ /(\S+):\s+(.*)/) { push @headers, ($1 => $2); } elsif ($_ =~ /(\S+)\s+(\S+)(\s+.*)?$/) { $method = $1; $url = $2; } else { die ("Invalid line: $_"); } } close FILE; return ($method, $url, @headers);}sub check_log_entry { my $log_entry = shift; my $url = shift; return 1 if ($log_entry =~ /(\d+\.\d+\.\d+\.\d+)\s+$url\s+\d+/); return 0;}sub do_request { my $url = shift; # Send the request my $headerobj = new HTTP::Headers(); my $response = $UA->request(HTTP::Request->new("GET" => $url, $headerobj)); my $reply = $response->content(); return $reply;}sub test_filtering { my $needed = shift; my $passed; my ($tests, $tried); my $random = rand(20000) % 6; @filter_tests = (); open FILTER_FILE, $PROXY_FILTER; while (<FILTER_FILE>) { chomp; $tests++; if ($tests % 10 == $random) { push @filter_tests, $_; print "\t Request $_ ...\n"; my $reply = do_request $_; if ($reply =~ /Forbidden/i || $reply =~ /Error/i) { $passed++; print "\t \t passed\n"; } else { print "\t \t did not pass\n"; } $tried++; last if ($tried == $needed); } } close FILTER_FILE; return $passed;}sub test_forwarding { my $needed = shift; my ($passed, $tried); my $random = rand(20000) % 10; @forward_tests = (); open FORWARD_FILE, $PROXY_FORWARD; while (<FORWARD_FILE>) { chomp; my ($url, $filename) = split; push @forward_tests, $url; print "\t Request $url ...\n"; my $reply = do_request($url); my $expected = read_file $TESTS_HOME.$filename; if ($reply ne $expected) { print "\t \t did not pass\n"; } else { $passed++; print "\t \t passed\n"; } $tried++; last if ($tried == $needed); } close FORWARD_FILE; return $passed;}sub test_logfile { my $score; sleep(2); my $existlog = 1; open(LOG, "< $PROXY_LOGFILE") or $existlog = 0; if ($existlog == 0) { print "\t \t did not pass not exist\n"; } else { # Just checking the last line should be good enough... my @lines = <LOG>; if (check_log_entry($lines[$#lines], $forward_tests[$#forward_tests])) { $score += 3; print "\t \t passed\n"; } else { $score += 2; print "\t \t did not pass the last line wrong\n"; } } close LOG; return $score;}############################################################## PART I: test correctness## Grading criteria for correctness (total 15)# 5 filtering# 5 forwarding# 3 logging# 2 SIGPIPE handling############################################################sub test_correctness { $PID = run_proxy(); return -1 if($PID == -1); print "\nTesting Correctness...\n" if($options{'debug'}); print "\n 1. Testing filtering...\n" if($options{'debug'}); my $score = test_filtering(5); print "\n 2. Testing forwarding...\n" if($options{'debug'}); $score += test_forwarding(5); print "\n 3. Testing crashing...\n" if ($options{'debug'}); my $temp = waitpid(-1, &WNOHANG); if ($temp == $PID) { $PORT ++; print "Oops, proxy crashed! restarting...\n"; last if($PID == -1); print "\t \t did not pass\n" if ($options{'debug'}); } else { print "\t \t passed\n" if($options{'debug'}); } return -1 if($PID == -1); print "\n 4. Testing log file...\n"; $score += test_logfile; print "\n 5. Testing SIGPIPE signal handling ...\n"; socket SOCK, AF_INET, SOCK_STREAM, getprotobyname('tcp'); my $addr = sockaddr_in($PORT, inet_aton("127.0.0.1")); connect SOCK, $addr; print SOCK "GET http://www.ietf.org/rfc/rfc2068.txt HTTP/1.0\r\n\r\n"; close SOCK; sleep(5); # Test crash? $temp = waitpid(-1, &WNOHANG); if ($temp == $PID) { $PORT ++; print "\t \t Oops, proxy crashed! did not pass\n"; } else { $score += 2; kill 9, $PID; print "\t \t passed\n"; } $PORT++; return $score;}############################################################## PART II: test threading## Grading criteria for threading# 2 filtering# 2 forwarding# 6 concurrency handling#############################################################sub test_threading { $PID = run_proxy(); return -1 if($PID == -1); print "\nTesting Threading... " if($options{'debug'}); ### # Connect to the proxy, print a little, but not all of what we want socket SOCK, AF_INET, SOCK_STREAM, getprotobyname('tcp'); my $addr = sockaddr_in($PORT, inet_aton("127.0.0.1")); connect SOCK, $addr; print SOCK "GET "; my $passed = test_filtering(2); $passed += test_forwarding(2); # Test crash? my $temp = waitpid(-1, &WNOHANG); if ($temp == $PID) { print "\t \t Oops, proxy crashed!\n"; close SOCK; } else { ### # finish our first request ### print SOCK "http://www.google.com HTTP/1.0\r\n\r\n"; sleep(3); close SOCK; $passed += 6; kill 9, $PID; } return $passed;}#### Main programif ($#ARGV < 2) { print_usage();}$PORT = $ARGV[0];if ($ARGV[2] eq "part1") { $PART1 = 1;} else { if ($ARGV[2] eq "part2") { $PART2 = 1; } else { if ($ARGV[2] eq "all") { $PART1 = 1; $PART2 = 1; } else { print_usage(); } }}$PROXY_LOGFILE = $ARGV[1];chomp $PWD;autoflush STDOUT 1;my $team = team();# test the correctnessif ($PART1 == 1) { $correctness_score = test_correctness();}if ($PART2 == 1) { $threading_score = test_threading();}if ($PART1 == 1) { print "$team:\tcorrectness_score = $correctness_score\n";}if ($PART2 == 1) { print "$team:\tthreading_score = $threading_score\n";}#open WEB, ">> $WEBLOG";#print WEB "$current_time <tr> <td bgcolor=#EEEEEE> $team </td> ";#print WEB "$current_time <tr> <td bgcolor=#EEEEEE> </td> ";#print WEB "<td bgcolor=#EEEEEE> $correctness_score </td> ";#print WEB "<td bgcolor=#EEEEEE> $threading_score </td> ";#printf WEB "<td bgcolor=#EEEEEE> %.4f </td> </tr>\n", $cacheing_score*100;#close WEB;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -