mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-06-06 18:33:13 +03:00
Make tmpdir non-writable for the read-only test
* On win32 this uses pywin32 package modules, so that's now in requirements-dev.txt. * I *think* that code is as clean as it's going to be. Windows is a pain with having you *append* a Deny ACL (rather than remove an Allow one), and then you have to find it in all the ACLs for the object in order to remove it by index. * Linux version of this using `os.chmod()` currently untested.
This commit is contained in:
parent
fbad8e240f
commit
ec230a9c05
@ -33,6 +33,8 @@ py2exe==0.10.3.0; sys_platform == 'win32'
|
|||||||
pytest==6.2.2
|
pytest==6.2.2
|
||||||
pytest-cov==2.11.1 # Pytest code coverage support
|
pytest-cov==2.11.1 # Pytest code coverage support
|
||||||
coverage[toml]==5.5 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs
|
coverage[toml]==5.5 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs
|
||||||
|
# For manipulating folder permissions and the like.
|
||||||
|
pywin32==300; sys_platform == 'win32'
|
||||||
|
|
||||||
|
|
||||||
# All of the normal requirements
|
# All of the normal requirements
|
||||||
|
@ -119,41 +119,66 @@ class TestJournalLock:
|
|||||||
assert locked == JournalLockResult.LOCKED
|
assert locked == JournalLockResult.LOCKED
|
||||||
|
|
||||||
def test_obtain_lock_with_tmpdir_ro(self, mock_journaldir: py_path_local_LocalPath):
|
def test_obtain_lock_with_tmpdir_ro(self, mock_journaldir: py_path_local_LocalPath):
|
||||||
"""Test JournalLock.obtain_lock() with tmpdir."""
|
"""Test JournalLock.obtain_lock() with read-only tmpdir."""
|
||||||
tmpdir = mock_journaldir
|
tmpdir = mock_journaldir
|
||||||
|
|
||||||
# Make tmpdir read-only ?
|
# Make tmpdir read-only ?
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
# Ref: <https://stackoverflow.com/a/12168268>
|
# Ref: <https://stackoverflow.com/a/12168268>
|
||||||
# 1. Look up the current user
|
|
||||||
user = os.environ.get('USERNAME')
|
|
||||||
|
|
||||||
# From pywin32
|
|
||||||
import ntsecuritycon as con
|
import ntsecuritycon as con
|
||||||
import win32security
|
import win32security
|
||||||
|
|
||||||
# 2. Fetch its details
|
# Fetch user details
|
||||||
winuser, domain, type = win32security.LookupAccountName("", user)
|
winuser, domain, type = win32security.LookupAccountName("", os.environ.get('USERNAME'))
|
||||||
|
# Fetch the current security of tmpdir for that user.
|
||||||
# 3. Fetch the current security of tmpdir for that user.
|
|
||||||
sd = win32security.GetFileSecurity(str(tmpdir), win32security.DACL_SECURITY_INFORMATION)
|
sd = win32security.GetFileSecurity(str(tmpdir), win32security.DACL_SECURITY_INFORMATION)
|
||||||
dacl = sd.GetSecurityDescriptorDacl() # instead of dacl = win32security.ACL()
|
dacl = sd.GetSecurityDescriptorDacl() # instead of dacl = win32security.ACL()
|
||||||
|
|
||||||
# 4. Add Write to Denied list
|
# Add Write to Denied list
|
||||||
dacl.AddAccessDeniedAce(win32security.ACL_REVISION, con.FILE_GENERIC_WRITE, winuser)
|
dacl.AddAccessDeniedAce(win32security.ACL_REVISION, con.FILE_WRITE_DATA, winuser)
|
||||||
# 5. Apply that change.
|
# Apply that change.
|
||||||
sd.SetSecurityDescriptorDacl(1, dacl, 0) # may not be necessary
|
sd.SetSecurityDescriptorDacl(1, dacl, 0) # may not be necessary
|
||||||
win32security.SetFileSecurity(str(tmpdir), win32security.DACL_SECURITY_INFORMATION, sd)
|
win32security.SetFileSecurity(str(tmpdir), win32security.DACL_SECURITY_INFORMATION, sd)
|
||||||
#
|
|
||||||
# And, we might need to undo all of that to exit tests cleanly ?
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
import stat
|
import stat
|
||||||
os.chmod(tmpdir, stat.S_IRUSR | stat.S_IUSR)
|
os.chmod(tmpdir, stat.S_IRUSR | stat.S_IXUSR)
|
||||||
|
|
||||||
jlock = JournalLock()
|
jlock = JournalLock()
|
||||||
|
|
||||||
# Check that an actual journaldir is handled correctly.
|
# Check that an actual journaldir is handled correctly.
|
||||||
locked = jlock.obtain_lock()
|
locked = jlock.obtain_lock()
|
||||||
|
|
||||||
|
# Revert permissions for test cleanup
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
# We can reuse winuser etc from before
|
||||||
|
import pywintypes
|
||||||
|
|
||||||
|
# We have to call GetAce() until we find one that looks like what
|
||||||
|
# we added.
|
||||||
|
i = 0
|
||||||
|
ace = dacl.GetAce(i)
|
||||||
|
while ace:
|
||||||
|
print(f'After {ace=}')
|
||||||
|
if ace[0] == (con.ACCESS_DENIED_ACE_TYPE, 0) and ace[1] == con.FILE_WRITE_DATA:
|
||||||
|
# Delete the Ace that we added
|
||||||
|
dacl.DeleteAce(i)
|
||||||
|
# Apply that change.
|
||||||
|
sd.SetSecurityDescriptorDacl(1, dacl, 0) # may not be necessary
|
||||||
|
win32security.SetFileSecurity(str(tmpdir), win32security.DACL_SECURITY_INFORMATION, sd)
|
||||||
|
print('Found the Ace we added, removing...')
|
||||||
|
break
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
try:
|
||||||
|
ace = dacl.GetAce(i)
|
||||||
|
|
||||||
|
except pywintypes.error:
|
||||||
|
print("Couldn't find the Ace we added, so can't remove")
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
os.chmod(tmpdir, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
|
||||||
|
|
||||||
print(f'{locked=}')
|
print(f'{locked=}')
|
||||||
assert locked == JournalLockResult.JOURNALDIR_READONLY
|
assert locked == JournalLockResult.JOURNALDIR_READONLY
|
||||||
|
Loading…
x
Reference in New Issue
Block a user