#!/usr/bin/perl -w

# Copyright (c) 2018, cPanel, LLC.
# All rights reserved.
# http://cpanel.net
#
# This is free software; you can redistribute it and/or modify it under the
# same terms as Perl itself. See L<perlartistic>.

use strict;
use warnings;

use Test2::Bundle::Extended;
use Test2::Tools::Explain;
use Test2::Plugin::NoWarnings;

use Overload::FileCheck q{:stat};

use Fcntl (
    '_S_IFMT',     # bit mask for the file type bit field
                   #'S_IFPERMS',   # bit mask for file perms.
    'S_IFSOCK',    # socket
    'S_IFLNK',     # symbolic link
    'S_IFREG',     # regular file
    'S_IFBLK',     # block device
    'S_IFDIR',     # directory
    'S_IFCHR',     # character device
    'S_IFIFO',     # FIFO
);

is stat_as_directory(), [ 0, 0, S_IFDIR,  (0) x 10 ], 'stat_as_directory';
is stat_as_file(),      [ 0, 0, S_IFREG,  (0) x 10 ], 'stat_as_file';
is stat_as_symlink(),   [ 0, 0, S_IFLNK,  (0) x 10 ], 'stat_as_symlink';
is stat_as_socket(),    [ 0, 0, S_IFSOCK, (0) x 10 ], 'stat_as_socket';
is stat_as_chr(),       [ 0, 0, S_IFCHR,  (0) x 10 ], 'stat_as_chr';
is stat_as_block(),     [ 0, 0, S_IFBLK,  (0) x 10 ], 'stat_as_block';
is stat_as_fifo(),      [ 0, 0, S_IFIFO,  (0) x 10 ], 'stat_as_fifo';

if ( $> == 0 ) {
    my ($username, $gid) = (getpwuid $>)[0, 3];
    my $groupname = getgrgid $gid;

    diag "Running privileged ($username/$groupname)";

    my $got = stat_as_file( uid => $username, gid => $groupname );

    is(
        $got,
        [ 0, 0, S_IFREG, (0) x 10 ],
        "stat_as_file( uid => $username, gid => $groupname )",
        explain $got,
    );
}

SKIP: {
    my $daemon_uid = getpwnam('daemon');
    skip "daemon uid unknown" unless defined $daemon_uid;

    my $wheel_gid  = getgrnam('wheel');
    skip "wheel gid unknown" unless defined $wheel_gid;

    if ( $daemon_uid && $wheel_gid ) {
        is stat_as_file( uid => 'daemon', gid => 'wheel' ),
          [ 0, 0, S_IFREG, 0, int $daemon_uid, int $wheel_gid, (0) x 7 ],
          'stat_as_file( uid => daemon, gid => wheel )';
    }

}

is stat_as_file( uid => 98765, gid => 1234 ),
  [ 0, 0, S_IFREG, 0, 98765, 1234, (0) x 7 ],
  'stat_as_file( uid => 98765, gid => 1234 )';

my @regular_file = ( 0, 0, S_IFREG, (0) x 10 );

my $now = time();
my $expect;

$expect = [@regular_file];
$expect->[7] = 1234;

is stat_as_file( size => 1234 ), $expect, 'size';

$expect = [@regular_file];
$expect->[8] = $now;
is stat_as_file( atime => $now ), $expect, 'atime';

$expect = [@regular_file];
$expect->[9] = $now;
is stat_as_file( mtime => $now ), $expect, 'mtime';

$expect = [@regular_file];
$expect->[10] = $now;
is stat_as_file( ctime => $now ), $expect, 'ctime';

$expect       = [@regular_file];
$expect->[8]  = 8;
$expect->[9]  = 9;
$expect->[10] = 10;
is stat_as_file( atime => 8, mtime => 9, ctime => 10 ), $expect, 'atime + mtime + ctime';

is stat_as_file( perms => 0755 ), [ 0, 0, S_IFREG | 0755, (0) x 10 ], 'stat_as_file with perms 0755';

# dev, ino, nlink, rdev — previously silently ignored
$expect = [@regular_file];
$expect->[0] = 42;
is stat_as_file( dev => 42 ), $expect, 'dev';

$expect = [@regular_file];
$expect->[1] = 99999;
is stat_as_file( ino => 99999 ), $expect, 'ino';

$expect = [@regular_file];
$expect->[3] = 3;
is stat_as_file( nlink => 3 ), $expect, 'nlink';

$expect = [@regular_file];
$expect->[6] = 7;
is stat_as_file( rdev => 7 ), $expect, 'rdev';

$expect = [@regular_file];
$expect->[11] = 4096;
is stat_as_file( blksize => 4096 ), $expect, 'blksize';

$expect = [@regular_file];
$expect->[12] = 8;
is stat_as_file( blocks => 8 ), $expect, 'blocks';

# st_ prefix variants
$expect = [@regular_file];
$expect->[0] = 55;
is stat_as_file( st_dev => 55 ), $expect, 'st_dev prefix';

$expect = [@regular_file];
$expect->[3] = 2;
is stat_as_file( ST_NLINK => 2 ), $expect, 'ST_NLINK uppercase prefix';

done_testing;
