diff --git a/README.md b/README.md index 8c559bd..71f48a8 100644 --- a/README.md +++ b/README.md @@ -48,16 +48,16 @@ Custom options: --allocation_requirements= Resource requirements to be allocate --allocation_timeout=, default=10 Allocation timeout in seconds --allocation_resource_list_file=, default=resources.json - Resource to be allocate ---allocation_lock_folder=, default= os tmp path allocation lock folder + Available resorces list +--allocation_lock_folder=, default= allocation lockfiles folder ``` *``* can be json-string or key-value pairs. requirements have to match available resources to make allocation possible. Key-value pairs example: `key=value&key2=value2` Example: + +See [example test](example/test_example.py). Usage: ``` cd example pytest --allocation_hostname localhost -s --allocation_lock_folder . . ``` - - diff --git a/lockable/plugin.py b/lockable/plugin.py index b0dfa6b..28d68f7 100644 --- a/lockable/plugin.py +++ b/lockable/plugin.py @@ -8,7 +8,7 @@ from contextlib import contextmanager import tempfile import pytest -from pydash import filter_, merge +from pydash import filter_, merge, count_by from func_timeout import func_timeout, FunctionTimedOut from filelock import Timeout, FileLock @@ -21,8 +21,8 @@ def pytest_addoption(parser): parser.addoption("--allocation_hostname", default=socket.gethostname(), help="Allocation host") parser.addoption("--allocation_requirements", default=None, help="Resource requirements to be allocate") parser.addoption("--allocation_timeout", default=10, help="Allocation timeout") - parser.addoption("--allocation_resource_list_file", default='resources.json', help="Resource to be allocate") - parser.addoption("--allocation_lock_folder", default=tempfile.gettempdir(), help="allocation lock folder") + parser.addoption("--allocation_resource_list_file", default='resources.json', help="Available resorces list") + parser.addoption("--allocation_lock_folder", default=tempfile.gettempdir(), help="Allocation lockfiles folder") def read_resources_list(filename): @@ -30,9 +30,22 @@ def read_resources_list(filename): with open(filename) as json_file: data = json.load(json_file) assert isinstance(data, list), 'data is not an list' + validate_json(data) return data +def validate_json(data): + counts = count_by(data, lambda obj: obj.get('id')) + no_ids = filter_(counts.keys(), lambda key: key is None) + if no_ids: + raise AssertionError('Invalid json, id property is missing') + + duplicates = filter_(counts.keys(), lambda key: counts[key] > 1) + if duplicates: + print(duplicates) + raise AssertionError(f"Invalid json, duplicate ids in {duplicates}") + + def parse_requirements(requirements_str): """ Parse requirements """ if not requirements_str: @@ -70,7 +83,6 @@ def release(): os.remove(lock_file) except OSError as error: print(error, file=sys.stderr) - return candidate, release except Timeout: raise AssertionError('not success') @@ -135,5 +147,5 @@ def test_foo(lockable_resource): print(f"Resource list: {json.dumps(resource_list)}") with lock(predicate, resource_list, timeout_s, lock_folder) as resource: for key, value in resource.items(): - record_testsuite_property(key, value) + record_testsuite_property(f'resource_{key}', value) yield resource diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 83c5cb3..3a65b51 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -11,7 +11,7 @@ import multiprocessing as mp from tempfile import mktemp from contextlib import contextmanager -from lockable.plugin import read_resources_list, parse_requirements, lock +from lockable.plugin import read_resources_list, parse_requirements, lock, validate_json HOSTNAME = socket.gethostname() @@ -135,3 +135,17 @@ def test_e2e(self): "--allocation_hostname", "localhost", join(example_root, "test_example.py")]) self.assertEqual(exit_code, 0) + + def test_valid_json(self): + data = [{"id": "12345"}] + validate_json(data) + + def test_duplicate_id_in_json(self): + data = [{"id": "1234"}, {"id": "12345"}, {"id": "12345"}] + with self.assertRaises(AssertionError): + validate_json(data) + + def test_missing_id_in_json(self): + data = [{"a": "1234"}, {"id": "12345"}, {"id": "123456"}] + with self.assertRaises(AssertionError): + validate_json(data)