summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@gmail.com>2019-08-27 17:31:18 +0200
committerTodd Gamblin <tgamblin@llnl.gov>2019-08-27 09:31:18 -0600
commit2e8aa6cb24bf883100ee3c7c9b7ded6e8d1ec38f (patch)
treeecf22afcb75f622ea72f4f679c5e799a34ec3527 /lib
parentdce9fc4d633e28dcdf106c44ea6d308b927e51e3 (diff)
downloadspack-2e8aa6cb24bf883100ee3c7c9b7ded6e8d1ec38f.tar.gz
spack-2e8aa6cb24bf883100ee3c7c9b7ded6e8d1ec38f.tar.bz2
spack-2e8aa6cb24bf883100ee3c7c9b7ded6e8d1ec38f.tar.xz
spack-2e8aa6cb24bf883100ee3c7c9b7ded6e8d1ec38f.zip
Configuration schema are checked against jsonschema draft 4 meta-schema (#10247)
fixes #10246
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/test/data/jsonschema_meta.json149
-rw-r--r--lib/spack/spack/test/python_version.py10
-rw-r--r--lib/spack/spack/test/schema.py41
3 files changed, 197 insertions, 3 deletions
diff --git a/lib/spack/spack/test/data/jsonschema_meta.json b/lib/spack/spack/test/data/jsonschema_meta.json
new file mode 100644
index 0000000000..bcbb84743e
--- /dev/null
+++ b/lib/spack/spack/test/data/jsonschema_meta.json
@@ -0,0 +1,149 @@
+{
+ "id": "http://json-schema.org/draft-04/schema#",
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "description": "Core schema meta-schema",
+ "definitions": {
+ "schemaArray": {
+ "type": "array",
+ "minItems": 1,
+ "items": { "$ref": "#" }
+ },
+ "positiveInteger": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "positiveIntegerDefault0": {
+ "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ]
+ },
+ "simpleTypes": {
+ "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ]
+ },
+ "stringArray": {
+ "type": "array",
+ "items": { "type": "string" },
+ "minItems": 1,
+ "uniqueItems": true
+ }
+ },
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "$schema": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {},
+ "multipleOf": {
+ "type": "number",
+ "minimum": 0,
+ "exclusiveMinimum": true
+ },
+ "maximum": {
+ "type": "number"
+ },
+ "exclusiveMaximum": {
+ "type": "boolean",
+ "default": false
+ },
+ "minimum": {
+ "type": "number"
+ },
+ "exclusiveMinimum": {
+ "type": "boolean",
+ "default": false
+ },
+ "maxLength": { "$ref": "#/definitions/positiveInteger" },
+ "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" },
+ "pattern": {
+ "type": "string",
+ "format": "regex"
+ },
+ "additionalItems": {
+ "anyOf": [
+ { "type": "boolean" },
+ { "$ref": "#" }
+ ],
+ "default": {}
+ },
+ "items": {
+ "anyOf": [
+ { "$ref": "#" },
+ { "$ref": "#/definitions/schemaArray" }
+ ],
+ "default": {}
+ },
+ "maxItems": { "$ref": "#/definitions/positiveInteger" },
+ "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" },
+ "uniqueItems": {
+ "type": "boolean",
+ "default": false
+ },
+ "maxProperties": { "$ref": "#/definitions/positiveInteger" },
+ "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" },
+ "required": { "$ref": "#/definitions/stringArray" },
+ "additionalProperties": {
+ "anyOf": [
+ { "type": "boolean" },
+ { "$ref": "#" }
+ ],
+ "default": {}
+ },
+ "definitions": {
+ "type": "object",
+ "additionalProperties": { "$ref": "#" },
+ "default": {}
+ },
+ "properties": {
+ "type": "object",
+ "additionalProperties": { "$ref": "#" },
+ "default": {}
+ },
+ "patternProperties": {
+ "type": "object",
+ "additionalProperties": { "$ref": "#" },
+ "default": {}
+ },
+ "dependencies": {
+ "type": "object",
+ "additionalProperties": {
+ "anyOf": [
+ { "$ref": "#" },
+ { "$ref": "#/definitions/stringArray" }
+ ]
+ }
+ },
+ "enum": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true
+ },
+ "type": {
+ "anyOf": [
+ { "$ref": "#/definitions/simpleTypes" },
+ {
+ "type": "array",
+ "items": { "$ref": "#/definitions/simpleTypes" },
+ "minItems": 1,
+ "uniqueItems": true
+ }
+ ]
+ },
+ "format": { "type": "string" },
+ "allOf": { "$ref": "#/definitions/schemaArray" },
+ "anyOf": { "$ref": "#/definitions/schemaArray" },
+ "oneOf": { "$ref": "#/definitions/schemaArray" },
+ "not": { "$ref": "#" }
+ },
+ "dependencies": {
+ "exclusiveMaximum": [ "maximum" ],
+ "exclusiveMinimum": [ "minimum" ]
+ },
+ "default": {}
+}
diff --git a/lib/spack/spack/test/python_version.py b/lib/spack/spack/test/python_version.py
index baee38a40a..6875aa4655 100644
--- a/lib/spack/spack/test/python_version.py
+++ b/lib/spack/spack/test/python_version.py
@@ -42,7 +42,10 @@ if sys.version_info[0] < 3:
os.path.join(spack_lib_path, 'external', 'jinja2', 'asyncfilters.py'),
os.path.join(spack_lib_path, 'external', 'jinja2', 'asyncsupport.py'),
os.path.join(spack_lib_path, 'external', 'yaml', 'lib3'),
- os.path.join(spack_lib_path, 'external', 'pyqver3.py')]
+ os.path.join(spack_lib_path, 'external', 'pyqver3.py'),
+ # Uses importlib
+ os.path.join(spack_lib_path, 'spack', 'test', 'schema.py')
+ ]
else:
import pyqver3 as pyqver
@@ -55,7 +58,10 @@ else:
os.path.join(spack_lib_path, 'external', 'jinja2', 'asyncfilters.py'),
os.path.join(spack_lib_path, 'external', 'jinja2', 'asyncsupport.py'),
os.path.join(spack_lib_path, 'external', 'yaml', 'lib'),
- os.path.join(spack_lib_path, 'external', 'pyqver2.py')]
+ os.path.join(spack_lib_path, 'external', 'pyqver2.py'),
+ # Uses importlib
+ os.path.join(spack_lib_path, 'spack', 'test', 'schema.py')
+ ]
def pyfiles(search_paths, exclude=()):
diff --git a/lib/spack/spack/test/schema.py b/lib/spack/spack/test/schema.py
index b638647641..88c824513a 100644
--- a/lib/spack/spack/test/schema.py
+++ b/lib/spack/spack/test/schema.py
@@ -3,10 +3,14 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+import json
+import os.path
+import sys
+
import jsonschema
import pytest
-
+import spack.paths
import spack.schema
@@ -50,6 +54,17 @@ def module_suffixes_schema():
}
+@pytest.fixture(scope='module')
+def meta_schema():
+ """Meta schema for JSON schema validation (Draft 4)"""
+ meta_schema_file = os.path.join(
+ spack.paths.test_path, 'data', 'jsonschema_meta.json'
+ )
+ with open(meta_schema_file) as f:
+ ms = json.load(f)
+ return ms
+
+
@pytest.mark.regression('9857')
def test_validate_spec(validate_spec_schema):
v = spack.schema.Validator(validate_spec_schema)
@@ -75,3 +90,27 @@ def test_module_suffixes(module_suffixes_schema):
v.validate(data)
assert 'is an invalid spec' in str(exc_err.value)
+
+
+@pytest.mark.regression('10246')
+@pytest.mark.skipif(
+ sys.version_info < (2, 7),
+ reason='requires python2.7 or higher because of importlib')
+@pytest.mark.parametrize('config_name', [
+ 'compilers',
+ 'config',
+ 'env',
+ 'merged',
+ 'mirrors',
+ 'modules',
+ 'packages',
+ 'repos'
+])
+def test_schema_validation(meta_schema, config_name):
+ import importlib
+ module_name = 'spack.schema.{0}'.format(config_name)
+ module = importlib.import_module(module_name)
+ schema = getattr(module, 'schema')
+
+ # If this validation throws the test won't pass
+ jsonschema.validate(schema, meta_schema)