#!/usr/bin/perl

# Copyright 2009, 2010 Kevin Ryde

# This file is part of File-Locate-Iterator.
#
# File-Locate-Iterator is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 3, or (at your option) any
# later version.
#
# File-Locate-Iterator is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with File-Locate-Iterator.  If not, see <http://www.gnu.org/licenses/>.

use 5.006;
use strict;
use warnings;
use Test::More;

## no critic (ProtectPrivateSubs)

eval { require File::Map; 1 }
  or plan skip_all => 'File::Map not available';
diag "File::Map version ",File::Map->VERSION;

plan tests => 16;

SKIP: { eval 'use Test::NoWarnings; 1'
          or skip 'Test::NoWarnings not available', 1; }

require File::Locate::Iterator::FileMap;
my $want_version = 9;
cmp_ok ($File::Locate::Iterator::FileMap::VERSION, '==', $want_version,
        'VERSION variable');
cmp_ok (File::Locate::Iterator::FileMap->VERSION,  '==', $want_version,
        'VERSION class method');
{ ok (eval { File::Locate::Iterator::FileMap->VERSION($want_version); 1 },
      "VERSION class check $want_version");
  my $check_version = $want_version + 1000;
  ok (! eval { File::Locate::Iterator::FileMap->VERSION($check_version); 1 },
      "VERSION class check $check_version");
}

require FindBin;
require File::Spec;
diag "FindBin $FindBin::Bin"; # don't let it seem used just once
my $samp_locatedb = File::Spec->catfile ($FindBin::Bin, 'samp.locatedb');

#-----------------------------------------------------------------------------
# _have_mmap_layer()

{
  open my $fh, '<', $samp_locatedb
    or die "oops, cannot open $samp_locatedb";
  ok (! File::Locate::Iterator::FileMap::_have_mmap_layer($fh),
      '_have_mmap_layer identify no :mmap layer');
}

# File::Map depends on 5.008 which has PerlIO.pm, not sure how much should
# do to work without it ... the layer checks are fairly important
#
my $have_PerlIO = eval { require PerlIO; };
if (! $have_PerlIO) { diag "PerlIO module not available -- $@"; }

SKIP: {
  $have_PerlIO
    or skip 'PerlIO module not available', 1;

  my $fh;
  my $nosuchlayer;
  do {
    local $SIG{'__WARN__'} = sub {
      if ($_[0] =~ /Unknown PerlIO layer/) {
        $nosuchlayer = 1;
      } else {
        warn $_[0];
      }
    };
    open $fh, '<:mmap', $samp_locatedb
  } or skip "Cannot open $samp_locatedb with mmap: $!", 1;
  if ($nosuchlayer) {
    skip "No :mmap layer available", 1;
  }
  diag "layers: ",PerlIO::get_layers($fh),"\n";
  ok (File::Locate::Iterator::FileMap::_have_mmap_layer($fh),
      '_have_mmap_layer identify :mmap layer');
}

#-----------------------------------------------------------------------------
# _bad_layer()

{
  open my $fh, '<', $samp_locatedb
    or die "oops, cannot open $samp_locatedb";
  binmode($fh)
    or die "oops, cannot set binary mode";
  is (File::Locate::Iterator::FileMap::_bad_layer($fh), undef,
      '_bad_layer on plain binary open');
}

SKIP: {
  $have_PerlIO
    or skip 'PerlIO module not available', 1;

  open my $fh, '<:crlf', $samp_locatedb
    or die "oops, cannot open $samp_locatedb with :crlf";
  is (File::Locate::Iterator::FileMap::_bad_layer($fh), 'crlf',
      '_bad_layer on :crlf');
}

#-----------------------------------------------------------------------------
# _round_up_pagesize()

is (File::Locate::Iterator::FileMap::_round_up_pagesize(0), 0,
    '_round_up_pagesize(0)');
diag "_PAGESIZE is ",File::Locate::Iterator::FileMap::_PAGESIZE();
is (File::Locate::Iterator::FileMap::_round_up_pagesize(1),
    File::Locate::Iterator::FileMap::_PAGESIZE(),
    '_round_up_pagesize(1)');

#-----------------------------------------------------------------------------
# _total_space()

is (File::Locate::Iterator::FileMap::_total_space(0), 0,
    '_total_space() zero initially');

is (File::Locate::Iterator::FileMap::_total_space(1),
    File::Locate::Iterator::FileMap::_PAGESIZE(),
    '_total_space(1)');

#-----------------------------------------------------------------------------
# get()/find() caching

{
  open my $fh, '<', $samp_locatedb
    or die "oops, cannot open $samp_locatedb";

  is (File::Locate::Iterator::FileMap->find($fh), undef,
      'find() not mapped yet');
  my $fm1 = File::Locate::Iterator::FileMap->get ($fh);
  my $fm2 = File::Locate::Iterator::FileMap->get ($fh);
  is ($fm1, $fm2, "get() re-used");

  my $fm = $fm1;
  Scalar::Util::weaken ($fm);
  undef $fm1;
  undef $fm2;
  is ($fm, undef, 'FileMap destroyed when weakened');
}


exit 0;
