Skip to content

Commit 5c04f56

Browse files
committed
Merge remote-tracking branch 'origin/master' into edge
2 parents 46efb1e + 5719c23 commit 5c04f56

File tree

4 files changed

+152
-2
lines changed

4 files changed

+152
-2
lines changed

tests/support.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from unittest import TestCase, main as testmain
3939

4040
TEST_BASE = os.path.dirname(__file__)
41+
TEST_DATA_DIR = os.path.join(TEST_BASE, "data")
4142
TEST_OUTPUT_DIR = os.path.join(TEST_BASE, "output")
4243
MIG_BASE = os.path.realpath(os.path.join(TEST_BASE, ".."))
4344
PY2 = sys.version_info[0] == 2
@@ -193,6 +194,8 @@ def logger(self):
193194
self._logger = FakeLogger()
194195
return self._logger
195196

197+
# custom assertions available for common use
198+
196199
def assertPathExists(self, relative_path):
197200
assert not os.path.isabs(
198201
relative_path), "expected relative path within output folder"
@@ -203,6 +206,13 @@ def assertPathExists(self, relative_path):
203206
else:
204207
return "file"
205208

209+
@staticmethod
210+
def pretty_display_path(absolute_path):
211+
assert os.path.isabs(absolute_path)
212+
relative_path = os.path.relpath(absolute_path, start=MIG_BASE)
213+
assert not relative_path.startswith('..')
214+
return relative_path
215+
206216

207217
def cleanpath(relative_path, test_case):
208218
assert isinstance(test_case, MigTestCase)
@@ -211,6 +221,12 @@ def cleanpath(relative_path, test_case):
211221
return tmp_path
212222

213223

224+
def fixturepath(relative_path):
225+
tmp_path = os.path.join(TEST_DATA_DIR, relative_path)
226+
assert (not stat.S_ISDIR(os.stat(tmp_path)))
227+
return tmp_path
228+
229+
214230
def temppath(relative_path, test_case, skip_clean=False):
215231
assert isinstance(test_case, MigTestCase)
216232
tmp_path = os.path.join(TEST_OUTPUT_DIR, relative_path)

tests/test_mig_shared_fileio.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
#
2020
# You should have received a copy of the GNU General Public License
2121
# along with this program; if not, write to the Free Software
22-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
23+
# USA.
2324
#
24-
# -- END_HEADER ---
25+
# --- END_HEADER ---
2526
#
2627

2728
"""Unit test fileio functions"""

tests/test_mig_shared_localfile.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# --- BEGIN_HEADER ---
4+
#
5+
# test_mig_shared_localfile - unit test of the corresponding mig shared module
6+
# Copyright (C) 2003-2024 The MiG Project by the Science HPC Center at UCPH
7+
#
8+
# This file is part of MiG.
9+
#
10+
# MiG is free software: you can redistribute it and/or modify
11+
# it under the terms of the GNU General Public License as published by
12+
# the Free Software Foundation; either version 2 of the License, or
13+
# (at your option) any later version.
14+
#
15+
# MiG is distributed in the hope that it will be useful,
16+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
# GNU General Public License for more details.
19+
#
20+
# You should have received a copy of the GNU General Public License
21+
# along with this program; if not, write to the Free Software
22+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
23+
# USA.
24+
#
25+
# --- END_HEADER ---
26+
#
27+
28+
"""Unit tests for the migrid module pointed to in the filename"""
29+
30+
import binascii
31+
from contextlib import contextmanager
32+
import errno
33+
import fcntl
34+
import os
35+
import sys
36+
import zipfile
37+
38+
sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__), ".")))
39+
40+
from support import MigTestCase, fixturepath, temppath, testmain
41+
from mig.shared.serverfile import LOCK_EX
42+
from mig.shared.localfile import LocalFile
43+
44+
DUMMY_FILE = 'some_file'
45+
46+
47+
@contextmanager
48+
def managed_localfile(lfd):
49+
"""Helper to assure localfiles are properly handled"""
50+
51+
assert isinstance(lfd, LocalFile)
52+
try:
53+
yield lfd
54+
finally:
55+
if lfd.get_lock_mode() != fcntl.LOCK_UN:
56+
pass
57+
if not lfd.closed:
58+
lfd.close()
59+
60+
61+
class MigSharedLocalfile(MigTestCase):
62+
"""Wrap unit tests for the corresponding module"""
63+
64+
def assertPathLockedExclusive(self, file_path):
65+
"""Custom assertion to check whether a file is exclusively locked"""
66+
67+
with open(file_path) as conflicting_f:
68+
reraise = None
69+
try:
70+
fcntl.flock(
71+
conflicting_f, fcntl.LOCK_NB | LOCK_EX)
72+
73+
# we were errantly able to acquire a lock, mark errored
74+
reraise = AssertionError("RERAISE_MUST_UNLOCK")
75+
except Exception as maybeerr:
76+
if getattr(maybeerr, 'errno', None) == errno.EAGAIN:
77+
# this is the expected exception - the logic tried to lock
78+
# a file that was (as we intended) already locked, meaning
79+
# this assertion has succeeded so we do not need to raise
80+
pass
81+
else:
82+
# some other error we did not expect occurred, record it
83+
reraise = AssertionError("RERAISE_NO_UNLOCK")
84+
85+
if reraise is not None:
86+
# if marked errored and locked, cleanup the lock we acquired but shouldn't
87+
if str(reraise) == 'RERAISE_MUST_UNLOCK':
88+
fcntl.flock(conflicting_f, fcntl.LOCK_NB | fcntl.LOCK_UN)
89+
90+
# raise a user-friendly error to aovid nested raise
91+
raise AssertionError(
92+
"expected locked file: %s" % self.pretty_display_path(file_path))
93+
94+
def test_localfile_locking(self):
95+
some_file = temppath(DUMMY_FILE, self)
96+
97+
with managed_localfile(LocalFile(some_file, 'w')) as lfd:
98+
lfd.lock(LOCK_EX)
99+
100+
self.assertEqual(lfd.get_lock_mode(), LOCK_EX)
101+
102+
self.assertPathLockedExclusive(some_file)
103+
104+
105+
if __name__ == '__main__':
106+
testmain()

tests/test_mig_shared_serial.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,31 @@
11
# -*- coding: utf-8 -*-
2+
#
3+
# --- BEGIN_HEADER ---
4+
#
5+
# test_mig_shared_serial - unit test of the corresponding mig shared module
6+
# Copyright (C) 2003-2024 The MiG Project by the Science HPC Center at UCPH
7+
#
8+
# This file is part of MiG.
9+
#
10+
# MiG is free software: you can redistribute it and/or modify
11+
# it under the terms of the GNU General Public License as published by
12+
# the Free Software Foundation; either version 2 of the License, or
13+
# (at your option) any later version.
14+
#
15+
# MiG is distributed in the hope that it will be useful,
16+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
# GNU General Public License for more details.
19+
#
20+
# You should have received a copy of the GNU General Public License
21+
# along with this program; if not, write to the Free Software
22+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
23+
# USA.
24+
#
25+
# --- END_HEADER ---
26+
#
27+
28+
"""Unit test serial functions"""
229

330
import os
431
import sys

0 commit comments

Comments
 (0)