1
0
Fork 0

Invert strict/lax schema validation

pull/9912/head
Guilliam Xavier 2021-05-24 11:51:04 +02:00
parent 9e2cb30dfb
commit 2d21dd675a
4 changed files with 87 additions and 23 deletions

View File

@ -2,8 +2,6 @@
"$schema": "https://json-schema.org/draft-04/schema#", "$schema": "https://json-schema.org/draft-04/schema#",
"title": "Package", "title": "Package",
"type": "object", "type": "object",
"additionalProperties": false,
"required": [ "name", "description" ],
"properties": { "properties": {
"name": { "name": {
"type": "string", "type": "string",

View File

@ -196,9 +196,9 @@ class JsonFile
$schemaData = (object) array('$ref' => $schemaFile); $schemaData = (object) array('$ref' => $schemaFile);
if ($schema === self::LAX_SCHEMA) { if ($schema !== self::LAX_SCHEMA) {
$schemaData->additionalProperties = true; $schemaData->additionalProperties = false;
$schemaData->required = array(); $schemaData->required = array('name', 'description');
} }
$validator = new Validator(); $validator = new Validator();

View File

@ -37,24 +37,6 @@ class ComposerSchemaTest extends TestCase
$this->assertEquals($expectedError, $this->check($json)); $this->assertEquals($expectedError, $this->check($json));
} }
public function testRequiredProperties()
{
$json = '{ }';
$result = $this->check($json);
$this->assertContains(array('property' => 'name', 'message' => 'The property name is required', 'constraint' => 'required'), $result);
$this->assertContains(array('property' => 'description', 'message' => 'The property description is required', 'constraint' => 'required'), $result);
$json = '{ "name": "vendor/package" }';
$this->assertEquals(array(
array('property' => 'description', 'message' => 'The property description is required', 'constraint' => 'required'),
), $this->check($json));
$json = '{ "description": "generic description" }';
$this->assertEquals(array(
array('property' => 'name', 'message' => 'The property name is required', 'constraint' => 'required'),
), $this->check($json));
}
public function testOptionalAbandonedProperty() public function testOptionalAbandonedProperty()
{ {
$json = '{"name": "vendor/package", "description": "description", "abandoned": true}'; $json = '{"name": "vendor/package", "description": "description", "abandoned": true}';

View File

@ -14,6 +14,7 @@ namespace Composer\Test\Json;
use Seld\JsonLint\ParsingException; use Seld\JsonLint\ParsingException;
use Composer\Json\JsonFile; use Composer\Json\JsonFile;
use Composer\Json\JsonValidationException;
use Composer\Test\TestCase; use Composer\Test\TestCase;
class JsonFileTest extends TestCase class JsonFileTest extends TestCase
@ -93,6 +94,89 @@ class JsonFileTest extends TestCase
{ {
$json = new JsonFile(__DIR__.'/Fixtures/composer.json'); $json = new JsonFile(__DIR__.'/Fixtures/composer.json');
$this->assertTrue($json->validateSchema()); $this->assertTrue($json->validateSchema());
$this->assertTrue($json->validateSchema(JsonFile::LAX_SCHEMA));
}
public function testSchemaValidationError()
{
$file = tempnam(sys_get_temp_dir(), 'c');
file_put_contents($file, '{ "name": null }');
$json = new JsonFile($file);
$expectedMessage = sprintf('"%s" does not match the expected JSON schema', $file);
$expectedError = 'name : NULL value found, but a string is required';
try {
$json->validateSchema();
$this->fail('Expected exception to be thrown (strict)');
} catch (JsonValidationException $e) {
$this->assertEquals($expectedMessage, $e->getMessage());
$this->assertContains($expectedError, $e->getErrors());
}
try {
$json->validateSchema(JsonFile::LAX_SCHEMA);
$this->fail('Expected exception to be thrown (lax)');
} catch (JsonValidationException $e) {
$this->assertEquals($expectedMessage, $e->getMessage());
$this->assertContains($expectedError, $e->getErrors());
}
unlink($file);
}
public function testSchemaValidationLaxAdditionalProperties()
{
$file = tempnam(sys_get_temp_dir(), 'c');
file_put_contents($file, '{ "name": "vendor/package", "description": "generic description", "foo": "bar" }');
$json = new JsonFile($file);
try {
$json->validateSchema();
$this->fail('Expected exception to be thrown (strict)');
} catch (JsonValidationException $e) {
$this->assertEquals(sprintf('"%s" does not match the expected JSON schema', $file), $e->getMessage());
$this->assertEquals(array('The property foo is not defined and the definition does not allow additional properties'), $e->getErrors());
}
$this->assertTrue($json->validateSchema(JsonFile::LAX_SCHEMA));
unlink($file);
}
public function testSchemaValidationLaxRequired()
{
$file = tempnam(sys_get_temp_dir(), 'c');
$json = new JsonFile($file);
$expectedMessage = sprintf('"%s" does not match the expected JSON schema', $file);
file_put_contents($file, '{ }');
try {
$json->validateSchema();
$this->fail('Expected exception to be thrown (strict)');
} catch (JsonValidationException $e) {
$this->assertEquals($expectedMessage, $e->getMessage());
$errors = $e->getErrors();
$this->assertContains('name : The property name is required', $errors);
$this->assertContains('description : The property description is required', $errors);
}
$this->assertTrue($json->validateSchema(JsonFile::LAX_SCHEMA));
file_put_contents($file, '{ "name": "vendor/package" }');
try {
$json->validateSchema();
$this->fail('Expected exception to be thrown (strict)');
} catch (JsonValidationException $e) {
$this->assertEquals($expectedMessage, $e->getMessage());
$this->assertEquals(array('description : The property description is required'), $e->getErrors());
}
$this->assertTrue($json->validateSchema(JsonFile::LAX_SCHEMA));
file_put_contents($file, '{ "description": "generic description" }');
try {
$json->validateSchema();
$this->fail('Expected exception to be thrown (strict)');
} catch (JsonValidationException $e) {
$this->assertEquals($expectedMessage, $e->getMessage());
$this->assertEquals(array('name : The property name is required'), $e->getErrors());
}
$this->assertTrue($json->validateSchema(JsonFile::LAX_SCHEMA));
unlink($file);
} }
public function testParseErrorDetectMissingCommaMultiline() public function testParseErrorDetectMissingCommaMultiline()