Test-MockFile

 view release on metacpan or  search on metacpan

t/autodie_all_functions.t  view on Meta::CPAN

#!/usr/bin/perl

# Test autodie exception throwing for all CORE override functions.
# Covers issue #264: autodie exceptions were only thrown for open/sysopen,
# leaving 12 other functions silently returning false under autodie.

use strict;
use warnings;

use Test::More;

# Skip if autodie is not available
BEGIN {
    eval { require autodie };
    if ($@) {
        plan skip_all => 'autodie not available';
    }
}

use autodie qw(opendir closedir unlink readlink mkdir rmdir
               rename link symlink truncate chmod chown utime);
use Test::MockFile qw(nostrict);

SKIP: {
    # Helper to verify autodie exception
    my $check_autodie = sub {
        my ($err, $func_name, $test_label) = @_;
        ok( defined $err, "$test_label: exception thrown" );
        if ( eval { require autodie::exception; 1 } ) {
            isa_ok( $err, 'autodie::exception', "$test_label: is autodie::exception" );
            like( $err->function, qr/\Q$func_name\E/, "$test_label: function is $func_name" );
        }
    };

    # ---- opendir ----

    subtest 'opendir dies on non-existent mocked dir' => sub {
        my $dir = Test::MockFile->dir("/ad_opendir_noexist_$$");

        my $died = !eval {
            opendir( my $dh, "/ad_opendir_noexist_$$" );
            1;
        };
        my $err = $@;

        ok( $died, "opendir dies on non-existent dir" );
        $check_autodie->( $err, 'opendir', 'opendir ENOENT' );
    };

    subtest 'opendir dies on ENOTDIR' => sub {
        my $file = Test::MockFile->file( "/ad_opendir_notdir_$$", "content" );

        my $died = !eval {
            opendir( my $dh, "/ad_opendir_notdir_$$" );
            1;
        };
        my $err = $@;

        ok( $died, "opendir dies on regular file (ENOTDIR)" );
        $check_autodie->( $err, 'opendir', 'opendir ENOTDIR' );
    };

    # ---- closedir ----

    subtest 'closedir dies on double-close' => sub {
        my $dir = Test::MockFile->new_dir("/ad_closedir_$$");

        opendir( my $dh, "/ad_closedir_$$" );
        closedir($dh);

        # Second close should die
        my $died = !eval {
            no warnings 'io';    # suppress closedir warning
            closedir($dh);
            1;
        };
        my $err = $@;

        ok( $died, "closedir dies on already-closed handle" );
        $check_autodie->( $err, 'closedir', 'closedir EBADF' );
    };

t/autodie_all_functions.t  view on Meta::CPAN


    # ---- rename ----

    subtest 'rename dies when source does not exist (ENOENT)' => sub {
        my $src = Test::MockFile->file("/ad_rename_nosrc_$$");
        my $dst = Test::MockFile->file("/ad_rename_dst_$$");

        my $died = !eval {
            rename( "/ad_rename_nosrc_$$", "/ad_rename_dst_$$" );
            1;
        };
        my $err = $@;

        ok( $died, "rename dies when source doesn't exist" );
        $check_autodie->( $err, 'rename', 'rename ENOENT' );
    };

    # ---- truncate ----

    subtest 'truncate dies on non-existent file (ENOENT)' => sub {
        my $file = Test::MockFile->file("/ad_trunc_noexist_$$");

        my $died = !eval {
            truncate( "/ad_trunc_noexist_$$", 0 );
            1;
        };
        my $err = $@;

        ok( $died, "truncate dies on non-existent file" );
        $check_autodie->( $err, 'truncate', 'truncate ENOENT' );
    };

    subtest 'truncate dies on directory (EISDIR)' => sub {
        my $dir = Test::MockFile->new_dir("/ad_trunc_dir_$$");

        my $died = !eval {
            truncate( "/ad_trunc_dir_$$", 0 );
            1;
        };
        my $err = $@;

        ok( $died, "truncate dies on directory" );
        $check_autodie->( $err, 'truncate', 'truncate EISDIR' );
    };

    # ---- chmod ----

    subtest 'chmod dies on non-existent file' => sub {
        my $file = Test::MockFile->file("/ad_chmod_noexist_$$");

        my $died = !eval {
            chmod( 0644, "/ad_chmod_noexist_$$" );
            1;
        };
        my $err = $@;

        ok( $died, "chmod dies on non-existent mocked file" );
        $check_autodie->( $err, 'chmod', 'chmod ENOENT' );
    };

    # ---- chown ----

    subtest 'chown dies on non-existent file' => sub {
        my $file = Test::MockFile->file("/ad_chown_noexist_$$");

        my $died = !eval {
            chown( $>, (split /\s/, $))[0], "/ad_chown_noexist_$$" );
            1;
        };
        my $err = $@;

        ok( $died, "chown dies on non-existent mocked file" );
        $check_autodie->( $err, 'chown', 'chown ENOENT' );
    };

    # ---- utime ----

    subtest 'utime dies on non-existent file' => sub {
        my $file = Test::MockFile->file("/ad_utime_noexist_$$");

        my $died = !eval {
            utime( time, time, "/ad_utime_noexist_$$" );
            1;
        };
        my $err = $@;

        ok( $died, "utime dies on non-existent mocked file" );
        $check_autodie->( $err, 'utime', 'utime ENOENT' );
    };

    # ---- Success paths still work ----

    subtest 'successful operations do not throw under autodie' => sub {
        my $dir  = Test::MockFile->new_dir("/ad_success_dir_$$");
        my $file = Test::MockFile->file( "/ad_success_file_$$", "content" );
        my $link_target = Test::MockFile->file("/ad_success_link_$$");
        my $hard_dest   = Test::MockFile->file("/ad_success_hard_$$");
        my $rename_dst  = Test::MockFile->file("/ad_success_rdst_$$");
        my $mkdir_tgt   = Test::MockFile->dir("/ad_success_mkdir_$$");
        my $rmdir_tgt   = Test::MockFile->new_dir("/ad_success_rmdir_$$");

        my $ok = eval {
            # opendir + closedir
            opendir( my $dh, "/ad_success_dir_$$" );
            closedir($dh);

            # symlink
            symlink( '/target', "/ad_success_link_$$" );

            # readlink
            my $target = readlink("/ad_success_link_$$");

            # link
            link( "/ad_success_file_$$", "/ad_success_hard_$$" );

            # truncate
            truncate( "/ad_success_file_$$", 3 );

            # rename
            rename( "/ad_success_file_$$", "/ad_success_rdst_$$" );

            # mkdir
            mkdir("/ad_success_mkdir_$$");

            # rmdir
            rmdir("/ad_success_rmdir_$$");

            # chmod
            chmod( 0755, "/ad_success_rdst_$$" );

            # chown
            chown( $>, (split /\s/, $))[0], "/ad_success_rdst_$$" );

            # utime
            utime( time, time, "/ad_success_rdst_$$" );

            # unlink
            unlink("/ad_success_rdst_$$");

            1;
        };

        ok( $ok, "all successful operations work under autodie" )
          or diag("Error: $@");
    };
}

done_testing();



( run in 0.793 second using v1.01-cache-2.11-cpan-5511b514fd6 )