"""Test file descriptor operations Made for Jython. """ import errno import os import sys import tempfile import test.test_support as test_support import unittest class TestFilenoTestCase(unittest.TestCase): def setUp(self): self.filename = tempfile.mktemp() self.fp = open(self.filename, 'w+') self.fd = self.fp.fileno() def tearDown(self): if self.fp: self.fp.close() os.remove(self.filename) def test_ftruncate(self): self.fp.write('jython filenos') self.fp.flush() os.fsync(self.fd) self.assertEqual(os.path.getsize(self.filename), 14) os.ftruncate(self.fd, 8) self.assertEqual(os.path.getsize(self.filename), 8) os.ftruncate(self.fd, 0) self.assertEqual(os.path.getsize(self.filename), 0) self.fp.close() raises(IOError, 9, os.ftruncate, self.fd, 0) def test_lseek(self): self.assertEqual(os.lseek(self.fd, 0, 1), 0) os.write(self.fd, 'jython filenos') os.lseek(self.fd, 7, 0) self.assertEqual(os.read(self.fd, 7), 'filenos') self.fp.close() raises(OSError, 9, os.lseek, self.fd, 0, 1) def test_read(self): self.fp.write('jython filenos') self.fp.flush() self.fp.seek(0) result = os.read(self.fd, 7) self.assertTrue(isinstance(result, str)) self.assertEqual(result, 'jython ') self.assertEqual(os.read(self.fd, 99), 'filenos') self.fp.close() raises(OSError, 9, os.read, self.fd, 1) def test_write(self): os.write(self.fd, 'jython filenos') self.fp.seek(0) self.assertEqual(self.fp.read(), 'jython filenos') self.fp.close() raises(OSError, 9, os.write, self.fd, 'The Larch') class TestOsOpenTestCase(unittest.TestCase): def setUp(self): self.filename = tempfile.mktemp() self.dir = None self.fd = None def tearDown(self): if self.fd: try: os.close(self.fd) except: pass if os.path.exists(self.filename): os.remove(self.filename) if self.dir: os.rmdir(self.dir) def test_open(self): # XXX: assert the mode of the file self.fd = os.open(self.filename, os.O_WRONLY | os.O_CREAT) self.assert_(os.path.exists(self.filename)) os.write(self.fd, 'jython') os.close(self.fd) self.fd = os.open(self.filename, os.O_WRONLY | os.O_APPEND) os.write(self.fd, ' filenos') os.close(self.fd) fp = open(self.filename) self.assertEquals(fp.read(), 'jython filenos') fp.close() # falls back to read only without O_WRONLY/O_RDWR self.fd = os.open(self.filename, os.O_APPEND) raises(OSError, 9, os.write, self.fd, 'new') # Acts as append on windows (seeks to the end) os.lseek(self.fd, 0, 0) self.assertEquals(os.read(self.fd, len('jython filenos')), 'jython filenos') os.close(self.fd) # falls back to read only without O_WRONLY/O_RDWR self.fd = os.open(self.filename, os.O_CREAT) raises(OSError, 9, os.write, self.fd, 'new') self.assertEquals(os.read(self.fd, len('jython filenos')), 'jython filenos') os.close(self.fd) # interpreted as RDWR self.fd = os.open(self.filename, os.O_RDONLY | os.O_RDWR) os.write(self.fd, 'test') os.lseek(self.fd, 0, 0) self.assertEquals(os.read(self.fd, 4), 'test') os.close(self.fd) def test_open_truncate(self): fp = open(self.filename, 'w') fp.write('hello') fp.close() self.assertEquals(os.path.getsize(self.filename), 5) self.fd = os.open(self.filename, os.O_TRUNC | os.O_RDWR) self.assertEquals(os.path.getsize(self.filename), 0) os.write(self.fd, 'truncated') os.lseek(self.fd, 0, 0) self.assertEquals(os.read(self.fd, len('truncated')), 'truncated') os.close(self.fd) self.fd = os.open(self.filename, os.O_TRUNC | os.O_WRONLY) self.assertEquals(os.path.getsize(self.filename), 0) os.write(self.fd, 'write only truncated') raises(OSError, 9, os.read, self.fd, 99) os.close(self.fd) fd = open(self.filename) self.assertEquals(fd.read(), 'write only truncated') fd.close() # Both fail on Windows, errno 22 """ # falls back to read only without O_WRONLY/O_RDWR, but truncates self.fd = os.open(self.filename, os.O_TRUNC) self.assertEquals(os.path.getsize(self.filename), 0) raises(OSError, 9, os.write, self.fd, 'new') self.assertEquals(os.read(self.fd, 99), '') os.close(self.fd) fp = open(self.filename, 'w') fp.write('and ') fp.close() self.assertEquals(os.path.getsize(self.filename), 4) # append with no write falls back to read, but still truncates self.fd = os.open(self.filename, os.O_TRUNC | os.O_APPEND) self.assertEquals(os.path.getsize(self.filename), 0) raises(OSError, 9, os.write, self.fd, 'new') os.close(self.fd) fp = open(self.filename, 'w') fp.write('and ') fp.close() self.assertEquals(os.path.getsize(self.filename), 4) """ def test_open_exclusive(self): self.assert_(not os.path.exists(self.filename)) # fails without O_CREAT raises(OSError, (2, self.filename), os.open, self.filename, os.O_EXCL) self.assert_(not os.path.exists(self.filename)) # creates, read only self.fd = os.open(self.filename, os.O_EXCL | os.O_CREAT) self.assert_(os.path.exists(self.filename)) raises(OSError, 9, os.write, self.fd, 'jython') self.assertEquals(os.read(self.fd, 99), '') os.close(self.fd) # not exclusive unless creating os.close(os.open(self.filename, os.O_EXCL)) raises(OSError, (17, self.filename), os.open, self.filename, os.O_CREAT | os.O_EXCL) raises(OSError, (17, self.filename), os.open, self.filename, os.O_CREAT | os.O_WRONLY | os.O_EXCL) raises(OSError, (17, self.filename), os.open, self.filename, os.O_CREAT | os.O_RDWR | os.O_EXCL) os.remove(self.filename) self.fd = os.open(self.filename, os.O_EXCL | os.O_RDWR | os.O_CREAT) os.write(self.fd, 'exclusive') os.lseek(self.fd, 0, 0) self.assertEquals(os.read(self.fd, len('exclusive')), 'exclusive') def test_open_sync(self): if not hasattr(os, 'O_SYNC'): return # Just ensure this works self.fd = os.open(self.filename, os.O_SYNC | os.O_WRONLY | os.O_CREAT) self.assert_(os.path.exists(self.filename)) os.write(self.fd, 'jython') raises(OSError, 9, os.read, self.fd, 99) os.close(self.fd) os.remove(self.filename) self.fd = os.open(self.filename, os.O_SYNC | os.O_RDWR | os.O_CREAT) self.assert_(os.path.exists(self.filename)) os.write(self.fd, 'jython') os.lseek(self.fd, 0, 0) self.assertEquals(os.read(self.fd, len('jython')), 'jython') os.close(self.fd) def test_open_sync_dir(self): if not hasattr(os, 'O_SYNC'): return self.dir = tempfile.mkdtemp() try: self.fd = os.open(self.dir, os.O_SYNC | os.O_RDWR) except OSError, ose: assert ose.errno == errno.EISDIR, ose.errno def test_bad_open(self): for mode in (os.O_WRONLY, os.O_WRONLY, os.O_RDWR): raises(OSError, (2, self.filename), os.open, self.filename, mode) open(self.filename, 'w').close() raises(OSError, (22, self.filename), os.open, self.filename, os.O_WRONLY | os.O_RDWR) class TestOsFdopenTestCase(unittest.TestCase): def setUp(self): self.filename = tempfile.mktemp() self.fd = None def tearDown(self): if self.fd: try: os.close(self.fd) except: pass if os.path.exists(self.filename): os.remove(self.filename) def test_fdopen(self): origw_fp = open(self.filename, 'w') origw = origw_fp.fileno() origr_fp = open(self.filename, 'r') origr = origr_fp.fileno() # Mode must begin with rwa raises(ValueError, "invalid file mode 'b'", os.fdopen, origr, 'b') # Refuse modes the original file doesn't support # XXX: allowed on windows CPython """ raises(OSError, '[Errno 22] Invalid argument', os.fdopen, origw, 'r') raises(OSError, '[Errno 22] Invalid argument', os.fdopen, origr, 'w') """ fp = os.fdopen(origw, 'w') fp.write('fdopen') # Windows CPython doesn't raise an exception here #raises(IOError, '[Errno 9] Bad file descriptor', # fp.read, 7) fp.close() fp = os.fdopen(origr) self.assertEquals(fp.read(), 'fdopen') # Windows CPython raises IOError [Errno 0] Error #raises(IOError, '[Errno 9] Bad file descriptor', # fp.write, 'test') raises(IOError, None, fp.write, 'test') fp.close() # Windows CPython raises OSError [Errno 0] Error for both these #raises(OSError, '[Errno 9] Bad file descriptor', # os.fdopen, origw, 'w') #raises(OSError, '[Errno 9] Bad file descriptor', # os.fdopen, origr, 'r') raises(OSError, None, os.fdopen, origw, 'w') raises(OSError, None, os.fdopen, origr, 'r') # These all raise IO/OSErrors on FreeBSD try: origw_fp.close() except: pass try: origr_fp.close() except: pass try: os.close(origw) except: pass try: os.close(origr) except: pass def raises(exc, expected, callable, *args): """Ensure the specified call raises exc. expected is compared against the exception message if not None. It can be a str, an errno or a 2 item tuple of errno/filename. The latter two being for comparison against EnvironmentErrors. """ if expected: if isinstance(expected, str): msg = expected else: errno = expected[0] if isinstance(expected, tuple) else expected msg = '[Errno %d] %s' % (errno, os.strerror(errno)) if isinstance(expected, tuple): msg += ': %r' % expected[1] try: callable(*args) except exc, val: if expected and str(val) != msg: raise test_support.TestFailed( "Message %r, expected %r" % (str(val), msg)) else: raise test_support.TestFailed("Expected %s" % exc) def test_main(): test_support.run_unittest(TestFilenoTestCase, TestOsOpenTestCase, TestOsFdopenTestCase) if __name__ == '__main__': test_main()