#! /usr/bin/perl

# This is a test script for apt-cacher

use strict;
use warnings;

use FindBin;
use Test::More qw(no_plan);

use Test::WWW::Mechanize;
use Net::SSL;
use Crypt::SSLeay; # not required

my $mech = Test::WWW::Mechanize->new;

# goto SKIP;

# Compilation and perlcritic
foreach (glob("$FindBin::Bin/../{apt-cacher,apt-cacher-*.pl,lib/*.pl}")) {
    next if /-cgi/;
    ok(system('perl', '-wc', $_) == 0, "Syntax $_") || exit;
    ok(system('perlcritic', '--verbose', '10', $_) == 0, "Perlcritic $_") || exit;
}

# Mirror mode
foreach my $server
  ('http://localhost:3143/',
   'http://localhost:3142/',
   'http://localhost:3124/',
   glob('{http://localhost/cgi-bin/,http://localhost:81/}' # Lighttpd and Apache
	. '{apt-cacher-src/,apt-cacher-src\?,apt-cacher-src\?/}')
  )
  {
      #Expected Success
      foreach my $test
	(
	 ['' => 'usage', 'Apt-cacher version'],
	 ['report' => 'report', 'Apt-cacher traffic report'],
	 ['ftp.uk.debian.org/debian/dists/stable/Release.gpg' => 'basic', '^$'],
	 ['debian/dists/stable/Release.gpg' => 'basic with host expansion', '^$'],
	 #	 ['http://ftp.uk.debian.org/debian/dists/stable/Release.gpg' => 'embedded http://'],
	 #	 ['ftp://ftp.uk.debian.org/debian/dists/stable/Release.gpg' => 'embedded ftp://']
	)
	  {
	      $mech->head_ok( $server.$test->[0], "HEAD $server ($test->[1])") || exit;
	      $mech->get_ok( $server.$test->[0], "GET $server ($test->[1])") || exit;
	      $mech->title_like(qr($test->[2])) || print 'Got: ' . $mech->response->content , ", Expected: 200\n" && exit;
	  }
      # Expected Failures

      # Expect 404
      foreach my $test
	(
	 ['debian/dists/stabl/Release.gpg' => 'N/A path'])
	  {
	      $mech->get($server.$test->[0]);
	      ok($mech->status == 404, "$server ($test->[1])") || do { print 'Got :', $mech->status, ", Expected: 404\n";
								    $mech->dump_headers;
								    exit;
								  }
	  }

      # Expect 403
      foreach my $test
	(
	 ['debian/dists/../stable/Release.gpg' => 'Bad path'],
	 ['../debian/dists/stable/Release.gpg' => 'Bad host'],
	 ['debian/dists/stable/' => 'No filename'],
	 ['debian/dists/stable/Release.not.permitted' => 'Bad filename']
	)
	  {
	      my $expected = 403;
	      $expected = 404 if ($test->[0] =~ /\.\./ && $server =~ m#/apt-cacher-src/# ); # Because CGI collapses the /../
	      $mech->get($server.$test->[0]);
	      ok($mech->status == $expected, "$server ($test->[1])") || do { print 'Got :', $mech->status,  ", Expected: $expected\n";
								    $mech->dump_headers;
								    exit;
								  }
	  }

      # Expect 502/504
      foreach my $test
	(
	 ['sillydnswithnochance/debian/dists/stable/Release.gpg' => 'N/A DNS']
	)
	  {
	      my $expected = 504;
	      $expected = 502 if ( $server =~ m\http://localhost:31(?:43|24)/\ ); # No upstream proxy
	      $mech->get($server.$test->[0]);
	      ok($mech->status == $expected, "$server ($test->[1])") || do { print 'Got :', $mech->status,  ", Expected: $expected\n";
								    $mech->dump_headers;
								    exit;
								  }
	  }
  }

SKIP:

# Proxy mode

$mech->proxy(['http', 'ftp', 'https'], 'http://localhost:3143/');
foreach my $test
  (
   ['http://ftp.uk.debian.org/debian/dists/stable/Release.gpg' => 'HTTP Proxy'],
   ['http://debian/dists/stable/Release.gpg' => 'HTTP Proxy with host expansion'],
   ['https://www.hindley.org.uk/~mark/debian/Packages.gz' => 'HTTPS Proxy GET'],
   ['ftp://ftp.uk.debian.org/debian/dists/stable/Release.gpg' => 'FTP Proxy']
  )
  {
      $mech->get_ok($test->[0], $test->[1]) ||  exit;
  }

foreach my $test
  (
   ['http://sillydnswithnochance/debian/dists/stable/Release.gpg' => 'HTTP Proxy Bad DNS', 504],
   ['http://ftp.uk.debian.org.uk/debian/../dists/stable/Release.gpg' => 'HTTP Proxy Bad URI', 403],
  )
  {
      $mech->get($test->[0]);
      ok($mech->status == $test->[2], $test->[1]) || do { print 'Got :', $mech->status, ", Expected: $test->[2]\n";
							 $mech->dump_headers;
							 exit;
						    }
  }
$mech->proxy(['http', 'ftp', 'https'], undef);

foreach my $test
  (
   ['https://www.hindley.org.uk/~mark/debian/Packages.gz' => 'HTTPS Proxy CONNECT', 200],
#   ['https://www.hindley.org.uk:22/~mark/debian/Packages.gz' => 'HTTPS Proxy CONNECT: Bad port', 403],
#   ['https://titan.hindleynet/~mark/debian/Packages.gz' => 'HTTPS Proxy CONNECT: Bad host', 403]
  )
  {
      local $ENV{HTTPS_PROXY} = 'http://localhost:3143';
      $mech->ssl_opts('verify_hostname' => 0);
      $mech->get($test->[0]);
      ok($mech->status == $test->[2], $test->[1]) ||  do { print 'Got :', $mech->status, ", Expected: $test->[2]\n";
							   $mech->dump_headers;
							   exit;
						       }
  }


# Individual tests

# SOAP post
$mech->proxy(['http'], 'http://localhost:3143/');
$mech->post('http://bugs.debian.org:80/cgi-bin/soap.cgi',
		 Content_Type => 'text/xml; charset=utf-8',
		 Content => '<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<n1:get_bugs xmlns:n1="Debbugs/SOAP/"
env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<keyvalue n2:arrayType="xsd:anyType[4]"
xmlns:n2="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="n2:Array">
<item xsi:type="xsd:string">severity</item>
<item n2:arrayType="xsd:anyType[3]"
xsi:type="n2:Array">
<item xsi:type="xsd:string">critical</item>
<item xsi:type="xsd:string">grave</item>
<item xsi:type="xsd:string">serious</item>
</item>
<item xsi:type="xsd:string">package</item>
<item n2:arrayType="xsd:anyType[1]"
xsi:type="n2:Array">
<item xsi:type="xsd:string">apt-cacher</item>
</item>
</keyvalue>
</n1:get_bugs>
</env:Body>
</env:Envelope>');
ok($mech->response->is_success, 'SOAP POST');

# Circular Proxy request
$mech->proxy(['http'], 'http://localhost:3142/');
$mech->get_ok('http://mercury.hindleynet:3142/debian/dists/stable/Release.gpg', 'HTTP Proxy circular request');
$mech->proxy(['http'], undef);

# Cache-Control: no-cache
$mech->get('http://localhost:3143/debian/dists/stable/Release', 'Cache-Control' => 'no-cache');
ok($mech->response->current_age<60, 'Cache-Control: no-cache') || do { print 'Got age:', $mech->response->current_age, "\n";
								       $mech->dump_headers;
								   };

# Cache-Control: max-age
$mech->get('http://localhost:3143/debian/dists/stable/Release', 'Cache-Control' => 'max-age=0');
ok($mech->response->current_age<60, 'Cache-Control: max-age') || do { print 'Got age:', $mech->response->current_age, "\n";
								      $mech->dump_headers;
								  };

# If-Modified-Since
$mech->head('http://localhost:3142/debian/dists/stable/Release', 'If-Modified-Since' => HTTP::Date::time2str);
ok($mech->status == 304, 'If-Modified-Since') || do { print 'Got :', $mech->status, "\n";
						      $mech->dump_headers;
						  };

# Range
$mech->head('http://localhost:3142/debian/dists/stable/Release', 'Range' => 'bytes=0-23' );
ok($mech->status == 206 && # Partial content
   $mech->response->content_length == 24, # Length is 0-23 inclusive
   'Range') || $mech->dump_headers;

# If-Range
$mech->head('http://localhost:3142/debian/dists/stable/Release', 'If-Range'  => HTTP::Date::time2str, 'Range' => 'bytes=0-23'  ); # Not Mod => Range returned
ok($mech->status == 206 && # Partial content
   $mech->response->content_length == 24, # Length is 0-23 inclusive
   'If-Range Not Modified') || $mech->dump_headers;

$mech->head('http://localhost:3142/debian/dists/stable/Release', 'If-Range'  => HTTP::Date::time2str  ); # Missing Range => Whole returned
ok($mech->status == 200, # Complete content
   'If-Range without Range') || $mech->dump_headers;

$mech->head('http://localhost:3142/debian/dists/stable/Release', 'If-Range'  => HTTP::Date::time2str(0) , 'Range' => 'bytes=0-23'  ); #  Mod => Whole returned
ok($mech->status == 200, # Complete content
   'If-Range Modified') || $mech->dump_headers;

# Package
$mech->get('http://localhost:3142/titan/~mark/debian/timeoutd_1.5-10moh_i386.deb', 'Cache-Control' => 'no-cache');
ok($mech->status == 200, 'Package fetch without checksum') || do { print 'Got :', $mech->status, "\n";
								   $mech->dump_headers;};
$mech->get('http://localhost:3143/titan/~mark/debian/timeoutd_1.5-10moh_i386.deb', 'Cache-Control' => 'no-cache');
ok($mech->status == 200, 'Package fetch with checksum') || do { print 'Got :', $mech->status, "\n";
								$mech->dump_headers;}
