Skip to content

Commit 41670d5

Browse files
committed
chore(test/Lib): resource
1 parent 01f48ba commit 41670d5

File tree

3 files changed

+250
-2
lines changed

3 files changed

+250
-2
lines changed

src/pylib/Lib/test/skipJs.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

22
tempfile
3+
resource
34
os_nojs
45
pathlib_nojs

src/pylib/Lib/test/support/os_helper.nim

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11

2+
from std/strutils import startsWith
23
import std/os as std_os
34
#import std/options
4-
#import ../../os
5+
import ../../os
6+
import ../../sys
7+
import ../../time
58

69
const
710
fn = "tempfiletest"
@@ -31,5 +34,78 @@ proc can_chmod: bool =
3134
let mode2 = os.stat(TESTFN).st_mode
3235
]#
3336

34-
37+
type S = string
38+
using filename: S
39+
40+
{.pragma: CbPragma, raises: [OSError], nimcall.}
41+
type Cb = proc (filename: S){.CbPragma.}
42+
template predeff(name; argname){.dirty.} =
43+
var `name Impl`: Cb
44+
template `asgn name`(impl){.dirty.} = `name Impl` = impl
45+
template `def name`(body){.dirty.} =
46+
proc `t name Impl`(argname: S){.CbPragma.} = body
47+
`asgn name` `t name Impl`
48+
49+
proc os_unlink(filename: S){.CbPragma.} =
50+
try: unlink(filename)
51+
except NotImplementedError as e: raise newException(OSError, "not impl arg", e)
52+
53+
predeff unlink, filename
54+
if sys.platform.startswith("win"):
55+
proc waitfor(fun: Cb, pathname: string, waitall=false){.raises: [OSError].} =
56+
# Perform the operation
57+
fun(pathname)
58+
# Now setup the wait loop
59+
var name, dirname: string
60+
if waitall:
61+
dirname = pathname
62+
else:
63+
(dirname, name) = os.path.split(pathname)
64+
if dirname == "": dirname = "."
65+
# Check for `pathname` to be removed from the filesystem.
66+
# The exponential backoff of the timeout amounts to a total
67+
# of ~1 second after which the deletion is probably an error
68+
# anyway.
69+
# Testing on an [email protected] shows that usually only 1 iteration is
70+
# required when contention occurs.
71+
var timeout = 0.01
72+
while timeout < 1.000:
73+
# Note we are only testing for the existence of the file(s) in
74+
# the contents of the directory regardless of any security or
75+
# access rights. If we have made it this far, we have sufficient
76+
# permissions to do that much using Python's equivalent of the
77+
# Windows API FindFirstFile.
78+
# Other Windows APIs can fail or give incorrect results when
79+
# dealing with files that are pending deletion.
80+
let L = os.listdir(dirname)
81+
if not (if waitall: len(L) > 0 else: name in L):
82+
return
83+
# Increase the timeout and try again
84+
try: time.sleep(timeout)
85+
except ValueError: doAssert false, "unreachable"
86+
timeout *= 2
87+
#[
88+
logging.getLogger("os_helper").warning(
89+
"tests may fail, delete still pending for %s",
90+
pathname,
91+
stack_info=True,
92+
stacklevel=4,
93+
)
94+
]#
95+
echo "tests may fail, delete still pending for " & pathname
96+
97+
defunlink:
98+
waitfor(
99+
os_unlink,
100+
filename
101+
)
102+
else:
103+
asgnunlink os_unlink
104+
#_rmdir = os.rmdir
105+
106+
proc unlink*(filename) =
107+
try:
108+
unlinkImpl(filename)
109+
except FileNotFoundError, NotADirectoryError:
110+
discard
35111

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
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

Comments
 (0)