Configuration schema are checked against jsonschema draft 4 meta-schema (#10247)
fixes #10246
This commit is contained in:
parent
dce9fc4d63
commit
2e8aa6cb24
149
lib/spack/spack/test/data/jsonschema_meta.json
Normal file
149
lib/spack/spack/test/data/jsonschema_meta.json
Normal file
@ -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": {}
|
||||||
|
}
|
@ -42,7 +42,10 @@
|
|||||||
os.path.join(spack_lib_path, 'external', 'jinja2', 'asyncfilters.py'),
|
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', 'jinja2', 'asyncsupport.py'),
|
||||||
os.path.join(spack_lib_path, 'external', 'yaml', 'lib3'),
|
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:
|
else:
|
||||||
import pyqver3 as pyqver
|
import pyqver3 as pyqver
|
||||||
@ -55,7 +58,10 @@
|
|||||||
os.path.join(spack_lib_path, 'external', 'jinja2', 'asyncfilters.py'),
|
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', 'jinja2', 'asyncsupport.py'),
|
||||||
os.path.join(spack_lib_path, 'external', 'yaml', 'lib'),
|
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=()):
|
def pyfiles(search_paths, exclude=()):
|
||||||
|
@ -3,10 +3,14 @@
|
|||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os.path
|
||||||
|
import sys
|
||||||
|
|
||||||
import jsonschema
|
import jsonschema
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
import spack.paths
|
||||||
import spack.schema
|
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')
|
@pytest.mark.regression('9857')
|
||||||
def test_validate_spec(validate_spec_schema):
|
def test_validate_spec(validate_spec_schema):
|
||||||
v = spack.schema.Validator(validate_spec_schema)
|
v = spack.schema.Validator(validate_spec_schema)
|
||||||
@ -75,3 +90,27 @@ def test_module_suffixes(module_suffixes_schema):
|
|||||||
v.validate(data)
|
v.validate(data)
|
||||||
|
|
||||||
assert 'is an invalid spec' in str(exc_err.value)
|
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user