|
| 1 | + |
| 2 | + |
| 3 | +import ./import_utils |
| 4 | +importPyLib resource |
| 5 | +pyimport os |
| 6 | +pyimport unittest |
| 7 | +pyimport sys |
| 8 | +pyimport time # sleep |
| 9 | +#from std/os as std_os import nil |
| 10 | +import std/unittest |
| 11 | +import ./support/os_helper |
| 12 | + |
| 13 | +var self = newTestCase() |
| 14 | + |
| 15 | +const CAN_GET_RLIMIT_FSIZE = compiles(resource.getrlimit(resource.RLIMIT_FSIZE)) |
| 16 | +const CAN_GET_RLIMIT_CPU = compiles(resource.getrlimit(resource.RLIMIT_CPU)) |
| 17 | + |
| 18 | +suite "ResourceTests": |
| 19 | + var cur, max: int |
| 20 | + skipIf(sys.platform == "vxworks", |
| 21 | + "setting RLIMIT_FSIZE is not supported on VxWorks"): test "fsize_ismax": |
| 22 | + when CAN_GET_RLIMIT_FSIZE: |
| 23 | + (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) |
| 24 | + #[RLIMIT_FSIZE should be RLIM_INFINITY, which will be a really big |
| 25 | +number on a platform with large file support. On these platforms, |
| 26 | +we need to test that the get/setrlimit functions properly convert |
| 27 | +the number to a C long long and that the conversion doesn't raise |
| 28 | +an error.]# |
| 29 | + self.assertEqual(resource.RLIM_INFINITY, typeof(resource.RLIM_INFINITY)(max)) |
| 30 | + resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) |
| 31 | + |
| 32 | + test "fsize_enforced": |
| 33 | + #def test_fsize_enforced(self): |
| 34 | + when compiles(resource.getrlimit(resource.RLIMIT_FSIZE)): |
| 35 | + (cur, max) = resource.getrlimit(resource.RLIMIT_FSIZE) |
| 36 | + # Check to see what happens when the RLIMIT_FSIZE is small. Some |
| 37 | + # versions of Python were terminated by an uncaught SIGXFSZ, but |
| 38 | + # pythonrun.c has been fixed to ignore that exception. If so, the |
| 39 | + # write() should return EFBIG when the limit is exceeded. |
| 40 | + |
| 41 | + # At least one platform has an unlimited RLIMIT_FSIZE and attempts |
| 42 | + # to change it raise ValueError instead. |
| 43 | + var limit_set = false |
| 44 | + try: |
| 45 | + try: |
| 46 | + resource.setrlimit(resource.RLIMIT_FSIZE, (1024, max)) |
| 47 | + limit_set = true |
| 48 | + except ValueError: |
| 49 | + limit_set = false |
| 50 | + |
| 51 | + var f = open(os_helper.TESTFN, fmWrite) |
| 52 | + try: |
| 53 | + for _ in 1..1024: |
| 54 | + f.write('X') |
| 55 | + try: |
| 56 | + f.write('Y') |
| 57 | + f.flushFile() |
| 58 | + # On some systems (e.g., Ubuntu on hppa) the flush() |
| 59 | + # doesn't always cause the exception, but the close() |
| 60 | + # does eventually. Try flushing several times in |
| 61 | + # an attempt to ensure the file is really synced and |
| 62 | + # the exception raised. |
| 63 | + for i in 0..4: |
| 64 | + time.sleep(0.1) # 100ms |
| 65 | + f.flushFile() |
| 66 | + except OSError: |
| 67 | + if not limit_set: |
| 68 | + raise |
| 69 | + if limit_set: |
| 70 | + # Close will attempt to flush the byte we wrote |
| 71 | + # Restore limit first to avoid getting a spurious error |
| 72 | + resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) |
| 73 | + finally: |
| 74 | + f.close() |
| 75 | + finally: |
| 76 | + if limit_set: |
| 77 | + resource.setrlimit(resource.RLIMIT_FSIZE, (cur, max)) |
| 78 | + os_helper.unlink(os_helper.TESTFN) |
| 79 | + |
| 80 | + test "fsize_toobig": |
| 81 | + # Be sure that setrlimit is checking for really large values |
| 82 | + let too_big = high int #10.float64.pow(50).int |
| 83 | + when CAN_GET_RLIMIT_FSIZE: |
| 84 | + let (_, max) = resource.getrlimit(resource.RLIMIT_FSIZE) |
| 85 | + try: |
| 86 | + resource.setrlimit(resource.RLIMIT_FSIZE, (too_big, max)) |
| 87 | + except #[OverflowError, ]#ValueError: |
| 88 | + discard |
| 89 | + try: |
| 90 | + resource.setrlimit(resource.RLIMIT_FSIZE, (max, too_big)) |
| 91 | + except #[OverflowError, ]#ValueError: |
| 92 | + discard |
| 93 | + |
| 94 | + skipUnless hasattr(resource, "getrusage"), "needs getrusage": test "getrusage": |
| 95 | + self.assertRaises(TypeError, resource.getrusage) |
| 96 | + |
| 97 | + {.push hint[XDeclaredButNotUsed]: off.} |
| 98 | + let |
| 99 | + _#[usageself]# = resource.getrusage(resource.RUSAGE_SELF) |
| 100 | + _#[usagechildren]# = resource.getrusage(resource.RUSAGE_CHILDREN) |
| 101 | + # May not be available on all systems. |
| 102 | + template t_may_fail(suffix) = |
| 103 | + when declared(resource.`RUSAGE suffix`): |
| 104 | + try: |
| 105 | + let `usage suffix` = resource.getrusage(resource.`RUSAGE suffix`) |
| 106 | + except ValueError#[, AttributeError]#: |
| 107 | + discard |
| 108 | + t_may_fail BOTH |
| 109 | + t_may_fail THREAD |
| 110 | + {.pop.} |
| 111 | + |
| 112 | + # Issue 6083: Reference counting bug |
| 113 | + skipIf sys.platform == "vxworks", "setting RLIMIT_CPU is not supported on VxWorks": test "setrusage_refcount": |
| 114 | + when CAN_GET_RLIMIT_CPU: |
| 115 | + let _#[limits]# = resource.getrlimit(resource.RLIMIT_CPU) |
| 116 | + type BadSequence = object |
| 117 | + proc len(self: BadSequence): int = 2 |
| 118 | + proc `[]`(self: BadSequence, key: int): int = |
| 119 | + if key in [0, 1]: |
| 120 | + return len(0..<1_000_000) |
| 121 | + raise newException(IndexDefect, "") |
| 122 | + let s = BadSequence() |
| 123 | + resource.setrlimit(resource.RLIMIT_CPU, s) |
| 124 | + |
| 125 | + test "pagesize": |
| 126 | + let pagesize = resource.getpagesize() |
| 127 | + self.assertIsInstance(pagesize, int) |
| 128 | + self.assertGreaterEqual(pagesize, 0) |
| 129 | + |
| 130 | + #[ No need to test |
| 131 | + skipUnless sys.platform in ["linux", "android"], "Linux only": test "linux_constants": |
| 132 | + for attr in ["MSGQUEUE", "NICE", "RTPRIO", "RTTIME", "SIGPENDING"]: |
| 133 | + try: |
| 134 | + self.assertIsInstance(getattr(resource, "RLIMIT_" & attr), int) |
| 135 | + except AttributeError: |
| 136 | + discard |
| 137 | +
|
| 138 | + test "freebsd_contants": |
| 139 | + for attr in ["SWAP", "SBSIZE", "NPTS"]: |
| 140 | + try: |
| 141 | + self.assertIsInstance(getattr(resource, "RLIMIT_" & attr), int) |
| 142 | + except AttributeError: |
| 143 | + discard |
| 144 | + ]# |
| 145 | + |
| 146 | +#[ XXX: TODO: after os.uname() -> sys.platform() -> support.requires_linux_version() |
| 147 | + skipUnless hasattr(resource, "prlimit"), "no prlimit": |
| 148 | + skipUnless support.requires_linux_version(2, 6, 36): |
| 149 | + test "prlimit": |
| 150 | + self.assertRaises(TypeError, resource.prlimit) |
| 151 | + # TODO: ProcessLookupError is not defined in oserr |
| 152 | + #self.assertRaises(ProcessLookupError, resource.prlimit, -1, resource.RLIMIT_AS) |
| 153 | + let limit = resource.getrlimit(resource.RLIMIT_AS) |
| 154 | + self.assertEqual(resource.prlimit(0, resource.RLIMIT_AS), limit) |
| 155 | + self.assertEqual(resource.prlimit(0, resource.RLIMIT_AS, limit), |
| 156 | + limit) |
| 157 | +
|
| 158 | + ]# |
| 159 | + # Issue 20191: Reference counting bug |
| 160 | + skipUnless hasattr(resource, "prlimit"), "no prlimit": |
| 161 | + #skipUnless support.requires_linux_version(2, 6, 36): |
| 162 | + test "prlimit_refcount": |
| 163 | + type BadSeq = object |
| 164 | + proc len(self: BadSeq): int = 2 |
| 165 | + |
| 166 | + let limits = resource.getrlimit(resource.RLIMIT_AS) |
| 167 | + let arrlimits = [limits[0], limits[1]] |
| 168 | + proc `[]`(self: BadSeq, key: int): int = |
| 169 | + return arrlimits[key] - 1 # new reference |
| 170 | + self.assertEqual(resource.prlimit(0, resource.RLIMIT_AS, BadSeq()), |
| 171 | + limits) |
0 commit comments