Skip to content

Commit

Permalink
Merge pull request #7 from xsuite/release/v0.1.2
Browse files Browse the repository at this point in the history
Release 0.1.2
  • Loading branch information
freddieknets authored Feb 28, 2024
2 parents 5eafc64 + e84a5d4 commit 94ccf16
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 105 deletions.
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
[tool.poetry]
name = "xaux"
version = "0.1.1"
version = "0.1.2"
description = "Support tools for Xsuite packages"
authors = ["Frederik Van der Veken <[email protected]>"]
authors = ["Frederik Van der Veken <[email protected]>",
"Konstantinos Paraschou <[email protected]"]
license = "Apache 2.0"
readme = "README.md"

Expand Down
40 changes: 40 additions & 0 deletions tests/_test_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import time
import json
from pathlib import Path
import shutil
from xaux import ProtectFile

ProtectFile._debug = True


def rewrite(pf, with_copy=False):
data = json.load(pf)
time.sleep(0.2)
data["myint"] += 1
if not with_copy:
pf.seek(0) # revert point to beginning of file
json.dump(data, pf, indent=4, sort_keys=True)
pf.truncate()
else: # write to another file and copy back
cfname = "_copy_" + pf.name
with open(cfname, "w") as cf:
json.dump(data, cf, indent=4, sort_keys=True)
shutil.copyfile(cfname, pf.name)
Path.unlink(Path(cfname))


def change_file_protected(fname, with_copy=False, max_lock_time=None):
with ProtectFile(fname, "r+", backup=False, wait=0.1, max_lock_time=max_lock_time) as pf:
rewrite(pf, with_copy=with_copy)
return


def change_file_standard(fname, with_copy=False):
with open(fname, "r+") as pf: # fails with this context
rewrite(pf)
return


def init_file(fname):
with ProtectFile(fname, "w", backup=False, wait=1) as pf:
json.dump({"myint": 0}, pf, indent=4)
46 changes: 5 additions & 41 deletions tests/test_deliberate_failure_and_protection.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,8 @@
from multiprocessing import Pool
import pytest
from xaux import ProtectFile
import json
from pathlib import Path
import time
import shutil


def rewrite(pf, with_copy=False):
data = json.load(pf)
time.sleep(0.2)
data["myint"] += 1
if not with_copy:
pf.seek(0) # revert point to beginning of file
json.dump(data, pf, indent=4, sort_keys=True)
pf.truncate()
else: # write to another file and copy back
cfname = "_copy_" + pf.name
with open(cfname, "w") as cf:
json.dump(data, cf, indent=4, sort_keys=True)
shutil.copyfile(cfname, pf.name)
Path.unlink(Path(cfname))


def change_file_protected(fname, with_copy=False):
with ProtectFile(fname, "r+", backup=False, wait=0.06) as pf:
rewrite(pf, with_copy=with_copy)
return


def change_file_standard(fname, with_copy=False):
with open(fname, "r+") as pf: # fails with this context
rewrite(pf)
return


def init_file(fname):
with ProtectFile(fname, "w", backup=False, wait=1) as pf:
json.dump({"myint": 0}, pf, indent=4)

from _test_helpers import init_file, change_file_protected, change_file_standard

def test_deliberate_failure():
fname = "test_standard.json"
Expand All @@ -48,10 +12,10 @@ def test_deliberate_failure():
with Pool(processes=workers) as pool:
pool.map(change_file_standard, [fname] * 4)

with open(fname, "r+") as pf: # fails with this context
with open(fname, "r+") as pf:
Path.unlink(Path(fname))
data = json.load(pf)
assert data["myint"] != workers # assert that result is wrong
Path.unlink(Path(fname))


@pytest.mark.parametrize("with_copy", [False, True])
Expand All @@ -63,7 +27,7 @@ def test_protection(with_copy):
with Pool(processes=workers) as pool:
pool.map(change_file_protected, [(fname)] * 4)

with open(fname, "r+") as pf: # fails with this context
with open(fname, "r+") as pf:
Path.unlink(Path(fname))
data = json.load(pf)
assert data["myint"] == workers
Path.unlink(Path(fname))
69 changes: 69 additions & 0 deletions tests/test_max_lock_time.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import json
from pathlib import Path
from _test_helpers import init_file, change_file_protected
from multiprocessing import Process
import os
import time
import signal


fname = "test_max_lock_time.json"


def test_max_lock_time():
init_file(fname)

procA = Process(target=change_file_protected, args=(fname, False, 1))
procB = Process(target=change_file_protected, args=(fname, False, 1))

procA.start() # Will take > 0.2s
time.sleep(0.18)
assert Path(fname+'.lock').exists()

# B will try to access the file while A is still running, and will try
# again 0.1s later by which time A has finished (and the lock will have
# disappeared).
procB.start()

procA.join()
procB.join()

with open(fname, "r+") as pf:
Path(fname).unlink()
data = json.load(pf)
assert data["myint"] == 2


def test_max_lock_time_crashed():
init_file(fname)

procA = Process(target=change_file_protected, args=(fname, False, 5))
procB = Process(target=change_file_protected, args=(fname, False, 5))

procA.start()
procB.start()
start = time.time()

# We kill process A after 0.1s such that we have a hanging lockfile
time.sleep(0.1)
os.kill(procA.pid, signal.SIGKILL)
procA.join()
assert Path(fname+'.lock').exists()

# After 6s (5s * 1.2) the lockfile is allowed to be force-freed.
# First we check that just before that, B was not able to alter the file:
time.sleep(6.1) # 6s max_lock_time + 0.2s rewrite time - 0.1s already waited
with open(fname, "r") as pf:
data = json.load(pf)
assert data["myint"] == 0
procB.join()

# Process B was able to complete its work directly after the max_lock_time
stop = time.time()
elapsed_time = stop - start
assert elapsed_time < 6.5

with open(fname, "r+") as pf:
Path(fname).unlink()
data = json.load(pf)
assert data["myint"] == 1
2 changes: 1 addition & 1 deletion tests/test_version.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from xaux import __version__

def test_version():
assert __version__ == '0.1.1'
assert __version__ == '0.1.2'

2 changes: 1 addition & 1 deletion xaux/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
# ===================
# Do not change
# ===================
__version__ = '0.1.1'
__version__ = '0.1.2'
# ===================
Loading

0 comments on commit 94ccf16

Please sign in to comment.