#!perl

use Benchmark qw(:all);
use URI::Encode::XS qw(uri_encode_utf8 uri_decode_utf8);
use URI::Fast qw(uri uri_split);
use URI::Split qw();
use URI;

my $POD;

if ($ARGV[0]) {
  open $POD, '>', './lib/URI/Fast/Benchmarks.pod' or die $!;
} else {
  my $str = '';
  open $POD, '>', \$str;
}

print $POD q{# PODNAME: URI::Fast::Benchmarks
# ABSTRACT: Benchmarks comparing URI::Fast and URI

=head1 BENCHMARKS

Various operations comparing L<URI::Fast> against L<URI>'s performance. The
script to recreate is included in the C<bench> folder of the distribution.

Tests were performed on my development machine, a 2015 MacBook Pro (2.7 GHz
Intel Core i5, 8GB 1867 MHz DDR3 RAM) using Perl 5.24 installed using
L<perlbrew|https://perlbrew.pl>.

};

my @urls = (
  '/foo/bar/baz',
  'http://www.test.com',
  'https://test.com/some/path?aaaa=bbbb&cccc=dddd&eeee=ffff',
  'https://user:pwd@192.168.0.1:8000/foo/bar?baz=bat&slack=fnord&asdf=the+quick%20brown+fox+%26+hound#foofrag',
);

my $encode_input = "Ῥόδος¢€" . q{! * ' ( ) ; : @ & = + $ , / ? # [ ] %} x 10;
my $decode_input = URI::Fast::encode($encode_input);

sub test {
  my ($msg, $count, $tests) = @_;
  local $| = 1;

  print "> $msg\n";
  my $results = cmpthese $count, $tests;

  print $POD "=head2 $msg\n\n";

  foreach (@$results) {
    printf $POD "  %15s%15s%15s%15s\n", @$_;
  }

  print $POD "\n\n";

  print "\n";
}

test 'Constructor', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]) },
  'URI::Fast' => sub{ my $uri = uri $urls[3] },
};

test 'Parse scheme', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); $uri->scheme },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; $uri->scheme },
};

test 'Update scheme', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[1]); $uri->scheme('https') },
  'URI::Fast' => sub{ my $uri = uri $urls[1]; $uri->scheme('https') },
};

test 'Parse authorization', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); $uri->host },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; $uri->host },
};

test 'Update authorization', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); $uri->host('test.com') },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; $uri->host('test.com') },
};

test 'Parse path (scalar)', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); my $p = $uri->path },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; my $p = $uri->path },
};

test 'Parse path (list)', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); my @p = $uri->path_segments },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; my @p = $uri->path },
};

test 'Update path (scalar)', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); $uri->path('/foo/bar') },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; $uri->path('/foo/bar') },
};

test 'Update path (array)', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); $uri->path('/' . join('/', 'foo', 'bar')) },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; $uri->path(['foo', 'bar']) },
};

test 'Parse query', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); my %q = $uri->query_form },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; my @v = $uri->param('asdf') },
};

test 'Set query parameter', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); $uri->query_form(foo => 'bar') },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; $uri->param('foo', 'bar') },
};

test 'Query form', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); my %q = $uri->query_form },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; my $q = $uri->query_hash },
};

test 'Query keys', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); my @k = keys %{$uri->query_form} },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; my @k = $uri->query_keys },
};

test 'Stringification', 500_000, {
  'URI' => sub{ my $uri = URI->new($urls[3]); my $str = "$uri" },
  'URI::Fast' => sub{ my $uri = uri $urls[3]; my $str = "$uri" },
};

test 'uri_split', 500_000, {
  'URI::Split' => sub{ my @uri = URI::Split::uri_split($urls[3]) },
  'URI::Fast' => sub{ my @uri = uri_split($urls[3]) },
};

test 'Encode', 2_000_000, {
  'URI::Encode::XS' => sub{ uri_encode_utf8($encode_input) },
  'URI::Fast' => sub{ URI::Fast::encode($encode_input) },
};

test 'Decode', 2_000_000, {
  'URI::Encode::XS' => sub{ uri_decode_utf8($decode_input) },
  'URI::Fast' => sub{ URI::Fast::decode($decode_input) },
};

close $POD;
