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