# Copyright (c) 2012, cPanel, Inc. # 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 the LICENSE file for further details. use strict; use warnings; use Filesys::POSIX (); use Filesys::POSIX::Mem (); use Filesys::POSIX::Bits; use Test::More ( 'tests' => 31 ); use Test::Exception; use Test::NoWarnings; { my $fs = Filesys::POSIX->new( Filesys::POSIX::Mem->new ); $fs->umask(022); my $fd = $fs->open( 'foo', $O_CREAT, 0600 ); ok( $fd == 3, 'Filesys::POSIX->open() for new file returns file descriptor 3 upon first call' ); ok( $fs->fstat($fd)->file, 'Filesys::POSIX->open() creates regular inode by default with $O_CREAT' ); ok( $fs->fstat($fd)->perms == 0600, 'Filesys::POSIX->open() handles mode argument appropriately' ); my $new_fd = $fs->open( 'bar', $O_CREAT ); ok( $new_fd == 4, 'Filesys::POSIX->open() for second new file returns file descriptor 4' ); $fs->close($fd); ok( $fs->open( 'bar', $O_RDONLY ) == 3, 'Filesys::POSIX->open() reclaims old file descriptors' ); $fs->close($fd); throws_ok { $fs->read( $fd, my $buf, 512 ); } qr/^Invalid file descriptor/, 'Filesys::POSIX->read() throws "Invalid file descriptor" exception on closed fd'; $fs->close($fd); $fs->close($new_fd); } { my $fs = Filesys::POSIX->new( Filesys::POSIX::Mem->new ); throws_ok { my $fd = $fs->open( 'foo', $O_CREAT | $O_WRONLY ); $fs->read( $fd, my $buf, 0 ); } qr/^Invalid argument/, "Filesys::POSIX->read() throws 'Invalid argument' when reading on write-only fd"; throws_ok { my $fd = $fs->open( 'foo', $O_CREAT | $O_RDONLY ); $fs->write( $fd, 'foo', 3 ); } qr/^Invalid argument/, "Filesys::POSIX->write() throws 'Invalid argument' when writing on read-only fd"; throws_ok { my $fd = $fs->open( 'foo', $O_CREAT | $O_RDONLY ); $fs->print( $fd, 'foo' ); } qr/^Invalid argument/, "Filesys::POSIX->print() throws 'Invalid argument' when writing on read-only fd"; throws_ok { my $fd = $fs->open( 'foo', $O_CREAT | $O_RDONLY ); $fs->printf( $fd, "Foo: %d\n", 1024 ); } qr/^Invalid argument/, "Filesys::POSIX->printf() throws 'Invalid argument' when writing on read-only fd"; lives_ok { my $fd = $fs->open( 'foo', $O_CREAT | $O_WRONLY ); $fs->print( $fd, "Hello, world\n" ); } "Filesys::POSIX->print() allows writing to writable fds"; lives_ok { my $fd = $fs->open( 'foo', $O_CREAT | $O_WRONLY ); $fs->printf( $fd, "Hello, world: %d\n", 1024 ); } "Filesys::POSIX->print() allows writing to writable fds"; my $fd = $fs->open( 'foo', $O_CREAT | $O_WRONLY ); ok( $fs->fdopen($fd), "Filesys::POSIX->fdopen() returns a raw file handle for an open file descriptor" ); } { my $fs = Filesys::POSIX->new( Filesys::POSIX::Mem->new ); my $fd = $fs->open( 'baz', $O_CREAT, $S_IFDIR ); my $inode = $fs->fstat($fd); ok( $inode->dir, 'Filesys::POSIX->open() allows for creation of directory inodes when passing $S_IFDIR' ); $fs->close($fd); } { my $fs = Filesys::POSIX->new( Filesys::POSIX::Mem->new ); my $fd = $fs->open( 'meow', $O_CREAT | $O_RDWR ); ok( $fs->tell($fd) == 0, 'Filesys::POSIX->tell() reports position 0 on newly-created files' ); ok( $fs->write( $fd, 'foo', 3 ) == 3, 'Filesys::POSIX->write() returns 3 for a 3-byte write operation' ); ok( $fs->tell($fd) == 3, 'Filesys::POSIX->tell() reports offset 3 after first 3-byte write operation' ); $fs->write( $fd, 'bar', 3 ); ok( $fs->tell($fd) == 6, 'Filesys::POSIX->tell() reports offset 6 after second 3-byte write operation' ); ok( $fs->seek( $fd, 0, $SEEK_SET ) == 0, 'Filesys::POSIX->seek() returns 0 when seeking to position 0' ); ok( $fs->seek( $fd, 3, $SEEK_SET ) == 3, 'Filesys::POSIX->seek() returns 3 when seeking to position 3' ); ok( $fs->read( $fd, my $buf, 3 ) == 3, 'Filesys::POSIX->read() returns 3 when reading 3 bytes' ); ok( $fs->tell($fd) == 6, 'Filesys::POSIX->tell() returns 6 after previous read() call' ); ok( $buf eq 'bar', 'Filesys::POSIX->read() populated read buffer with expected result' ); ok( $fs->seek( $fd, 9, $SEEK_SET ) == 9, 'Filesys::POSIX->seek() allows seeking beyond file size' ); ok( $fs->write( $fd, 'baz', 3 ) == 3, 'Filesys::POSIX->write() allows random access writes' ); ok( $fs->fstat($fd)->{'size'} == 12, 'Filesys::POSIX->write() updated inode size to 12 bytes' ); ok( $fs->seek( $fd, 0, $SEEK_SET ) == 0, 'Filesys::POSIX->seek() allows seeking to beginning of file' ); ok( $fs->read( $fd, $buf, 12 ) == 12, 'Filesys::POSIX->read() read expected number of bytes' ); ok( $buf eq "foobar\x00\x00\x00baz", 'Filesys::POSIX->read() populated buffer with expected results' ); } { my $fs = Filesys::POSIX->new( Filesys::POSIX::Mem->new ); throws_ok { $fs->open('foo'); } qr/^Invalid argument/, 'Filesys::POSIX->open() dies when no flags are passed'; }