1import unittest
2from test import test_support
3import time
4
5resource = test_support.import_module('resource')
6
7# This test is checking a few specific problem spots with the resource module.
8
9class ResourceTest(unittest.TestCase):
10
11    def test_args(self):
12        self.assertRaises(TypeError, resource.getrlimit)
13        self.assertRaises(TypeError, resource.getrlimit, 42, 42)
14        self.assertRaises(TypeError, resource.setrlimit)
15        self.assertRaises(TypeError, resource.setrlimit, 42, 42, 42)
16
17    def test_fsize_ismax(self):
18        try:
19            (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE)
20        except AttributeError:
21            self.skipTest('RLIMIT_FSIZE not available')
22        # RLIMIT_FSIZE should be RLIM_INFINITY, which will be a really big
23        # number on a platform with large file support.  On these platforms,
24        # we need to test that the get/setrlimit functions properly convert
25        # the number to a C long long and that the conversion doesn't raise
26        # an error.
27        self.assertEqual(resource.RLIM_INFINITY, max)
28        resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max))
29
30    def test_fsize_enforced(self):
31        try:
32            (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE)
33        except AttributeError:
34            self.skipTest('RLIMIT_FSIZE not available')
35        # Check to see what happens when the RLIMIT_FSIZE is small.  Some
36        # versions of Python were terminated by an uncaught SIGXFSZ, but
37        # pythonrun.c has been fixed to ignore that exception.  If so, the
38        # write() should return EFBIG when the limit is exceeded.
39
40        # At least one platform has an unlimited RLIMIT_FSIZE and attempts
41        # to change it raise ValueError instead.
42        try:
43            try:
44                resource.setrlimit(resource.RLIMIT_FSIZE, (1024, max))
45                limit_set = True
46            except ValueError:
47                limit_set = False
48            f = open(test_support.TESTFN, "wb")
49            try:
50                f.write("X" * 1024)
51                try:
52                    f.write("Y")
53                    f.flush()
54                    # On some systems (e.g., Ubuntu on hppa) the flush()
55                    # doesn't always cause the exception, but the close()
56                    # does eventually.  Try flushing several times in
57                    # an attempt to ensure the file is really synced and
58                    # the exception raised.
59                    for i in range(5):
60                        time.sleep(.1)
61                        f.flush()
62                except IOError:
63                    if not limit_set:
64                        raise
65                if limit_set:
66                    # Close will attempt to flush the byte we wrote
67                    # Restore limit first to avoid getting a spurious error
68                    resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max))
69            finally:
70                f.close()
71        finally:
72            if limit_set:
73                resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max))
74            test_support.unlink(test_support.TESTFN)
75
76    def test_fsize_toobig(self):
77        # Be sure that setrlimit is checking for really large values
78        too_big = 10L**50
79        try:
80            (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE)
81        except AttributeError:
82            self.skipTest('RLIMIT_FSIZE not available')
83        try:
84            resource.setrlimit(resource.RLIMIT_FSIZE, (too_big, max))
85        except (OverflowError, ValueError):
86            pass
87        try:
88            resource.setrlimit(resource.RLIMIT_FSIZE, (max, too_big))
89        except (OverflowError, ValueError):
90            pass
91
92    def test_getrusage(self):
93        self.assertRaises(TypeError, resource.getrusage)
94        self.assertRaises(TypeError, resource.getrusage, 42, 42)
95        usageself = resource.getrusage(resource.RUSAGE_SELF)
96        usagechildren = resource.getrusage(resource.RUSAGE_CHILDREN)
97        # May not be available on all systems.
98        try:
99            usageboth = resource.getrusage(resource.RUSAGE_BOTH)
100        except (ValueError, AttributeError):
101            pass
102
103    # Issue 6083: Reference counting bug
104    def test_setrusage_refcount(self):
105        try:
106            limits = resource.getrlimit(resource.RLIMIT_CPU)
107        except AttributeError:
108            self.skipTest('RLIMIT_CPU not available')
109        class BadSequence:
110            def __len__(self):
111                return 2
112            def __getitem__(self, key):
113                if key in (0, 1):
114                    return len(tuple(range(1000000)))
115                raise IndexError
116
117        resource.setrlimit(resource.RLIMIT_CPU, BadSequence())
118
119def test_main(verbose=None):
120    test_support.run_unittest(ResourceTest)
121
122if __name__ == "__main__":
123    test_main()
124