Home | History | Annotate | Download | only in test
      1 """Test program for the fcntl C module.
      2 
      3 OS/2+EMX doesn't support the file locking operations.
      4 
      5 """
      6 import os
      7 import struct
      8 import sys
      9 import unittest
     10 from test.test_support import (verbose, TESTFN, unlink, run_unittest,
     11     import_module, cpython_only)
     12 
     13 # Skip test if no fcntl module.
     14 fcntl = import_module('fcntl')
     15 
     16 
     17 # TODO - Write tests for flock() and lockf().
     18 
     19 def get_lockdata():
     20     if sys.platform.startswith('atheos'):
     21         start_len = "qq"
     22     else:
     23         try:
     24             os.O_LARGEFILE
     25         except AttributeError:
     26             start_len = "ll"
     27         else:
     28             start_len = "qq"
     29 
     30     if (sys.platform.startswith(('netbsd', 'freebsd', 'openbsd', 'bsdos'))
     31         or sys.platform == 'darwin'):
     32         if struct.calcsize('l') == 8:
     33             off_t = 'l'
     34             pid_t = 'i'
     35         else:
     36             off_t = 'lxxxx'
     37             pid_t = 'l'
     38         lockdata = struct.pack(off_t + off_t + pid_t + 'hh', 0, 0, 0,
     39                                fcntl.F_WRLCK, 0)
     40     elif sys.platform in ['aix3', 'aix4', 'hp-uxB', 'unixware7']:
     41         lockdata = struct.pack('hhlllii', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
     42     elif sys.platform in ['os2emx']:
     43         lockdata = None
     44     else:
     45         lockdata = struct.pack('hh'+start_len+'hh', fcntl.F_WRLCK, 0, 0, 0, 0, 0)
     46     if lockdata:
     47         if verbose:
     48             print 'struct.pack: ', repr(lockdata)
     49     return lockdata
     50 
     51 lockdata = get_lockdata()
     52 
     53 
     54 class BadFile:
     55     def __init__(self, fn):
     56         self.fn = fn
     57     def fileno(self):
     58         return self.fn
     59 
     60 class TestFcntl(unittest.TestCase):
     61 
     62     def setUp(self):
     63         self.f = None
     64 
     65     def tearDown(self):
     66         if self.f and not self.f.closed:
     67             self.f.close()
     68         unlink(TESTFN)
     69 
     70     def test_fcntl_fileno(self):
     71         # the example from the library docs
     72         self.f = open(TESTFN, 'w')
     73         rv = fcntl.fcntl(self.f.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
     74         if verbose:
     75             print 'Status from fcntl with O_NONBLOCK: ', rv
     76         if sys.platform not in ['os2emx']:
     77             rv = fcntl.fcntl(self.f.fileno(), fcntl.F_SETLKW, lockdata)
     78             if verbose:
     79                 print 'String from fcntl with F_SETLKW: ', repr(rv)
     80         self.f.close()
     81 
     82     def test_fcntl_file_descriptor(self):
     83         # again, but pass the file rather than numeric descriptor
     84         self.f = open(TESTFN, 'w')
     85         rv = fcntl.fcntl(self.f, fcntl.F_SETFL, os.O_NONBLOCK)
     86         if sys.platform not in ['os2emx']:
     87             rv = fcntl.fcntl(self.f, fcntl.F_SETLKW, lockdata)
     88         self.f.close()
     89 
     90     def test_fcntl_bad_file(self):
     91         with self.assertRaises(ValueError):
     92             fcntl.fcntl(-1, fcntl.F_SETFL, os.O_NONBLOCK)
     93         with self.assertRaises(ValueError):
     94             fcntl.fcntl(BadFile(-1), fcntl.F_SETFL, os.O_NONBLOCK)
     95         with self.assertRaises(TypeError):
     96             fcntl.fcntl('spam', fcntl.F_SETFL, os.O_NONBLOCK)
     97         with self.assertRaises(TypeError):
     98             fcntl.fcntl(BadFile('spam'), fcntl.F_SETFL, os.O_NONBLOCK)
     99 
    100     @cpython_only
    101     def test_fcntl_bad_file_overflow(self):
    102         from _testcapi import INT_MAX, INT_MIN
    103         # Issue 15989
    104         with self.assertRaises(ValueError):
    105             fcntl.fcntl(INT_MAX + 1, fcntl.F_SETFL, os.O_NONBLOCK)
    106         with self.assertRaises(ValueError):
    107             fcntl.fcntl(BadFile(INT_MAX + 1), fcntl.F_SETFL, os.O_NONBLOCK)
    108         with self.assertRaises(ValueError):
    109             fcntl.fcntl(INT_MIN - 1, fcntl.F_SETFL, os.O_NONBLOCK)
    110         with self.assertRaises(ValueError):
    111             fcntl.fcntl(BadFile(INT_MIN - 1), fcntl.F_SETFL, os.O_NONBLOCK)
    112 
    113     def test_fcntl_64_bit(self):
    114         # Issue #1309352: fcntl shouldn't fail when the third arg fits in a
    115         # C 'long' but not in a C 'int'.
    116         try:
    117             cmd = fcntl.F_NOTIFY
    118             # This flag is larger than 2**31 in 64-bit builds
    119             flags = fcntl.DN_MULTISHOT
    120         except AttributeError:
    121             self.skipTest("F_NOTIFY or DN_MULTISHOT unavailable")
    122         fd = os.open(os.path.dirname(os.path.abspath(TESTFN)), os.O_RDONLY)
    123         try:
    124             # This will raise OverflowError if issue1309352 is present.
    125             fcntl.fcntl(fd, cmd, flags)
    126         except IOError:
    127             pass  # Running on a system that doesn't support these flags.
    128         finally:
    129             os.close(fd)
    130 
    131 
    132 def test_main():
    133     run_unittest(TestFcntl)
    134 
    135 if __name__ == '__main__':
    136     test_main()
    137