From 681cd6dc03c77313f2b45472727fc87f2a251b64 Mon Sep 17 00:00:00 2001 From: bspriggs Date: Mon, 16 Apr 2018 19:27:58 -0700 Subject: [PATCH 1/7] Add six as a dependency --- Pipfile | 1 + Pipfile.lock | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index e9305ee..a230445 100644 --- a/Pipfile +++ b/Pipfile @@ -7,6 +7,7 @@ name = "pypi" [packages] docopt = "*" +six = "*" [requires] python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index fa4dc0f..77e6a4a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "aa581d46a740183fe5556b542e1f993a8518ed00e6f306bb168a2910014f4bbc" + "sha256": "636c68712fe4e10a833935edd659d2fc32782c76102e54cfe9039478d30dc2ea" }, "pipfile-spec": 6, "requires": { @@ -22,6 +22,14 @@ ], "index": "pypi", "version": "==0.6.2" + }, + "six": { + "hashes": [ + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + ], + "index": "pypi", + "version": "==1.11.0" } }, "develop": {} From 751d82b5413a9a3e00fd15dfc2ad5208e34b474c Mon Sep 17 00:00:00 2001 From: bspriggs Date: Mon, 16 Apr 2018 19:28:24 -0700 Subject: [PATCH 2/7] Add tests for configuration validator --- tests/fixtures/sample_config_invalid.json | 36 +++++++++++++++++++++++ tests/test_validate.py | 20 +++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/fixtures/sample_config_invalid.json create mode 100644 tests/test_validate.py diff --git a/tests/fixtures/sample_config_invalid.json b/tests/fixtures/sample_config_invalid.json new file mode 100644 index 0000000..e601526 --- /dev/null +++ b/tests/fixtures/sample_config_invalid.json @@ -0,0 +1,36 @@ +{ + "run_type": "i made my own run type and its cool", + "meta": { + "creation_date": "2012 23 1 1", + "name": "single run", + "company": "ACME" + }, + + "speccjbb": { + "injectors": 4, + "backends": 2, + "jvm_path": "/path/to/jvm", + "jar_path": "/path/to/specjbb/jar" + }, + + "jvm_options": [ + "option 1", + "option 2", + "option 3" + ], + + "props": { + "specjbb.controller.type": "runtype", + "specjbb.controller.rtcurve.start": "0.0", + "specjbb.controller.type": "HBIR" + }, + + "other": { + "stuff": "we might decide to", + "add": "later" + }, + + "extra": { + "options": "we don't use yet" + } +} diff --git a/tests/test_validate.py b/tests/test_validate.py new file mode 100644 index 0000000..75c4560 --- /dev/null +++ b/tests/test_validate.py @@ -0,0 +1,20 @@ +from schema import SchemaError +from unittest import TestCase +import json +from src.validate import validate + +class ConfigValidatorTest(TestCase): + def test_empty_config_does_not_validate(self): + with self.assertRaises(SchemaError): + validate({}) + + def test_valid_config_does_validate(self): + with open('src/fixtures/sample_config.json') as f: + j = json.loads(f.read()) + self.assertTrue(validate(j)) + + def test_invalid_config_does_not_validate(self): + with self.assertRaises(SchemaError): + with open('src/fixtures/sample_config_invalid.json') as f: + j = json.loads(f.read()) + self.assertFalse(validate(j)) From de463b84c3d1791ad1bdd8031cb5c41abd111d09 Mon Sep 17 00:00:00 2001 From: bspriggs Date: Mon, 16 Apr 2018 19:28:35 -0700 Subject: [PATCH 3/7] Add configuration validator --- src/__init__.py | 4 ++++ src/validate.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/__init__.py create mode 100644 src/validate.py diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..0deb77e --- /dev/null +++ b/src/__init__.py @@ -0,0 +1,4 @@ +from os.path import dirname, basename, isfile +import glob +modules = glob.glob(dirname(__file__)+"/*.py") +__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')] diff --git a/src/validate.py b/src/validate.py new file mode 100644 index 0000000..cbf92e0 --- /dev/null +++ b/src/validate.py @@ -0,0 +1,31 @@ +from schema import Schema, And, Or, Optional + +# used for python2 and python3 string types +from six import text_type + +def is_stringy(v): + return type(v) is text_type + +ConfigSchema = Schema({ + Optional("meta"): { + object: object + }, + + "specjbb": { + "run_type": And(is_stringy, + lambda rt: rt.lower() in ["hbir", "hbir_rt", "preset", "loadlevel"]), + "kit_version": is_stringy, + "tag": is_stringy, + "jdk": is_stringy, + "numa_node": int, + "data": is_stringy, + "rt_start": int, + "duration": int, + "t": [int], + "jvm_options": [is_stringy], + }, + + }) + +def validate(unvalidated): + return ConfigSchema.validate(unvalidated) From 6850b537b77c94c83be83bc0a1c5df8dc465aa2d Mon Sep 17 00:00:00 2001 From: bspriggs Date: Mon, 16 Apr 2018 19:28:50 -0700 Subject: [PATCH 4/7] Add main.py utilization of configuration validator --- main.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index 363f822..6f57819 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ Usage: main.py run [--props ] + main.py validate main.py (-h | --help) main.py --version @@ -15,6 +16,7 @@ from docopt import docopt # source imports +from src import validate def to_list(s): if s['run_type'].lower() in ["hbir", "hbir_rt"]: @@ -59,11 +61,20 @@ def do_run(arguments): cwd=os.path.join(os.path.dirname(__file__), 'scripts') ) +def do_validate(arguments): + """ + Validate a configuration based on the schema provided. + """ + with open(arguments[''], 'r') as f: + args = json.loads(f.read()) + return validate.validate(args) is None + # dictionary of runnables # these are functions that take arguments from the # command line and do something with them. do = { 'run': do_run, + 'validate': do_validate, } if __name__ == "__main__": @@ -73,5 +84,5 @@ def do_run(arguments): if arguments[key]: r = func(arguments) - if r is None: - exit(1) + if r is not None: + exit(r) From 61f47e0964b8c9e0925b46954905d833c02b7e1c Mon Sep 17 00:00:00 2001 From: bspriggs Date: Mon, 16 Apr 2018 19:30:04 -0700 Subject: [PATCH 5/7] Rename test_validate class --- src/test_validate.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test_validate.py diff --git a/src/test_validate.py b/src/test_validate.py new file mode 100644 index 0000000..d91917f --- /dev/null +++ b/src/test_validate.py @@ -0,0 +1,21 @@ +from schema import SchemaError +from unittest import TestCase +import json +from src.validate import validate + +class TestConfigValidator(TestCase): + def test_empty_config_does_not_validate(self): + with self.assertRaises(SchemaError): + validate({}) + + def test_example_config_does_validate(self): + with open('example_config.json') as f: + j = json.loads(f.read()) + assert 'specjbb' in j + self.assertTrue(validate(j)) + + def test_invalid_config_does_not_validate(self): + with self.assertRaises(SchemaError): + with open('src/fixtures/sample_config_invalid.json') as f: + j = json.loads(f.read()) + self.assertFalse(validate(j)) From b2abac260ed99929bc3509d17c866cc0955bedfd Mon Sep 17 00:00:00 2001 From: bspriggs Date: Mon, 16 Apr 2018 19:32:14 -0700 Subject: [PATCH 6/7] Move test location and use proper fixture directory --- src/test_validate.py | 21 --------------------- tests/test_validate.py | 9 +++++---- 2 files changed, 5 insertions(+), 25 deletions(-) delete mode 100644 src/test_validate.py diff --git a/src/test_validate.py b/src/test_validate.py deleted file mode 100644 index d91917f..0000000 --- a/src/test_validate.py +++ /dev/null @@ -1,21 +0,0 @@ -from schema import SchemaError -from unittest import TestCase -import json -from src.validate import validate - -class TestConfigValidator(TestCase): - def test_empty_config_does_not_validate(self): - with self.assertRaises(SchemaError): - validate({}) - - def test_example_config_does_validate(self): - with open('example_config.json') as f: - j = json.loads(f.read()) - assert 'specjbb' in j - self.assertTrue(validate(j)) - - def test_invalid_config_does_not_validate(self): - with self.assertRaises(SchemaError): - with open('src/fixtures/sample_config_invalid.json') as f: - j = json.loads(f.read()) - self.assertFalse(validate(j)) diff --git a/tests/test_validate.py b/tests/test_validate.py index 75c4560..5c2e1bc 100644 --- a/tests/test_validate.py +++ b/tests/test_validate.py @@ -3,18 +3,19 @@ import json from src.validate import validate -class ConfigValidatorTest(TestCase): +class TestConfigValidator(TestCase): def test_empty_config_does_not_validate(self): with self.assertRaises(SchemaError): validate({}) - def test_valid_config_does_validate(self): - with open('src/fixtures/sample_config.json') as f: + def test_example_config_does_validate(self): + with open('example_config.json') as f: j = json.loads(f.read()) + assert 'specjbb' in j self.assertTrue(validate(j)) def test_invalid_config_does_not_validate(self): with self.assertRaises(SchemaError): - with open('src/fixtures/sample_config_invalid.json') as f: + with open('tests/fixtures/sample_config_invalid.json') as f: j = json.loads(f.read()) self.assertFalse(validate(j)) From 61e819b1ecf6cb20503e4e2c7afba311b4139360 Mon Sep 17 00:00:00 2001 From: bspriggs Date: Mon, 16 Apr 2018 19:34:55 -0700 Subject: [PATCH 7/7] Install schema --- Pipfile | 1 + Pipfile.lock | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index a230445..42db06f 100644 --- a/Pipfile +++ b/Pipfile @@ -8,6 +8,7 @@ name = "pypi" [packages] docopt = "*" six = "*" +schema = "*" [requires] python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index 77e6a4a..26d2128 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "636c68712fe4e10a833935edd659d2fc32782c76102e54cfe9039478d30dc2ea" + "sha256": "78c5a2bc0522cc2d0bea110d2ebd8638b4b0532eb80062ecf93262cd446fcc01" }, "pipfile-spec": 6, "requires": { @@ -23,6 +23,14 @@ "index": "pypi", "version": "==0.6.2" }, + "schema": { + "hashes": [ + "sha256:410f44cb025384959d20deef00b4e1595397fa30959947a4f0d92e9c84616f35", + "sha256:a058daf5d926e4ece9f13c4c2366a836143ca7913ef053c5023c569e00175b2a" + ], + "index": "pypi", + "version": "==0.6.7" + }, "six": { "hashes": [ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",