diff --git a/.travis.yml b/.travis.yml index 4037422a..9e7174fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,10 @@ sudo: false language: php +cache: + directories: + - $HOME/.composer/cache + matrix: fast_finish: true include: @@ -8,16 +12,20 @@ matrix: - php: 5.4 - php: 5.5 - php: 5.6 + - php: 7.0 env: WITH_COVERAGE=true - - php: 7 + - php: 7.1 + - php: 'nightly' - php: hhvm + allow_failures: + - php: 'nightly' before_install: - - if [[ "$WITH_COVERAGE" != "true" && "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then phpenv config-rm xdebug.ini; fi + - if [[ "$WITH_COVERAGE" != "true" && "$TRAVIS_PHP_VERSION" != "hhvm" && "$TRAVIS_PHP_VERSION" != "nightly" && "$TRAVIS_PHP_VERSION" != "7.1" ]]; then phpenv config-rm xdebug.ini; fi - composer selfupdate install: - - travis_retry composer install --no-interaction --prefer-source + - travis_retry composer install --no-interaction --prefer-dist script: - - if [[ "$WITH_COVERAGE" == "true" ]]; then vendor/bin/phpunit --coverage-text; else vendor/bin/phpunit; fi + - if [[ "$WITH_COVERAGE" == "true" ]]; then composer coverage; else composer test; fi diff --git a/composer.json b/composer.json index 537faa70..9948575b 100644 --- a/composer.json +++ b/composer.json @@ -54,5 +54,9 @@ "branch-alias": { "dev-master": "3.0.x-dev" } + }, + "scripts": { + "test" : "vendor/bin/phpunit", + "coverage" : "vendor/bin/phpunit --coverage-text" } } diff --git a/src/JsonSchema/Constraints/CollectionConstraint.php b/src/JsonSchema/Constraints/CollectionConstraint.php index 1b1554aa..b65173de 100644 --- a/src/JsonSchema/Constraints/CollectionConstraint.php +++ b/src/JsonSchema/Constraints/CollectionConstraint.php @@ -106,7 +106,7 @@ protected function validateItems($value, $schema = null, JsonPointer $path = nul // Treat when we have more schema definitions than values, not for empty arrays if (count($value) > 0) { for ($k = count($value); $k < count($schema->items); $k++) { - $this->checkUndefined(new UndefinedConstraint(), $schema->items[$k], $path, $k); + $this->checkUndefined($this->factory->createInstanceFor('undefined'), $schema->items[$k], $path, $k); } } } diff --git a/src/JsonSchema/Constraints/Constraint.php b/src/JsonSchema/Constraints/Constraint.php index c5683a64..95a63971 100644 --- a/src/JsonSchema/Constraints/Constraint.php +++ b/src/JsonSchema/Constraints/Constraint.php @@ -22,9 +22,6 @@ */ abstract class Constraint implements ConstraintInterface { - protected $schemaStorage; - protected $checkMode = self::CHECK_MODE_NORMAL; - protected $uriRetriever; protected $errors = array(); protected $inlineSchemaProperty = '$schema'; @@ -33,70 +30,16 @@ abstract class Constraint implements ConstraintInterface const CHECK_MODE_COERCE = 0x00000004; /** - * @var null|Factory + * @var Factory */ - private $factory; + protected $factory; /** - * @param int $checkMode - * @param SchemaStorage $schemaStorage - * @param UriRetrieverInterface $uriRetriever * @param Factory $factory */ - public function __construct( - $checkMode = self::CHECK_MODE_NORMAL, - SchemaStorage $schemaStorage = null, - UriRetrieverInterface $uriRetriever = null, - Factory $factory = null - ) { - $this->checkMode = $checkMode; - $this->uriRetriever = $uriRetriever; - $this->factory = $factory; - $this->schemaStorage = $schemaStorage; - } - - /** - * @return UriRetrieverInterface $uriRetriever - */ - public function getUriRetriever() - { - if (is_null($this->uriRetriever)) { - $this->setUriRetriever(new UriRetriever); - } - - return $this->uriRetriever; - } - - /** - * @return Factory - */ - public function getFactory() + public function __construct(Factory $factory = null) { - if (!$this->factory) { - $this->factory = new Factory($this->getSchemaStorage(), $this->getUriRetriever(), $this->checkMode); - } - - return $this->factory; - } - - /** - * @return SchemaStorage - */ - public function getSchemaStorage() - { - if (is_null($this->schemaStorage)) { - $this->schemaStorage = new SchemaStorage($this->getUriRetriever()); - } - - return $this->schemaStorage; - } - - /** - * @param UriRetrieverInterface $uriRetriever - */ - public function setUriRetriever(UriRetrieverInterface $uriRetriever) - { - $this->uriRetriever = $uriRetriever; + $this->factory = $factory ? : new Factory(); } /** @@ -124,7 +67,9 @@ public function addError(JsonPointer $path = null, $message, $constraint='', arr */ public function addErrors(array $errors) { - $this->errors = array_merge($this->errors, $errors); + if ($errors) { + $this->errors = array_merge($this->errors, $errors); + } } /** @@ -182,7 +127,7 @@ protected function incrementPath(JsonPointer $path = null, $i) */ protected function checkArray($value, $schema = null, JsonPointer $path = null, $i = null) { - $validator = $this->getFactory()->createInstanceFor('collection'); + $validator = $this->factory->createInstanceFor('collection'); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); @@ -199,7 +144,7 @@ protected function checkArray($value, $schema = null, JsonPointer $path = null, */ protected function checkObject($value, $schema = null, JsonPointer $path = null, $i = null, $patternProperties = null) { - $validator = $this->getFactory()->createInstanceFor('object'); + $validator = $this->factory->createInstanceFor('object'); $validator->check($value, $schema, $path, $i, $patternProperties); $this->addErrors($validator->getErrors()); @@ -215,7 +160,7 @@ protected function checkObject($value, $schema = null, JsonPointer $path = null, */ protected function checkType($value, $schema = null, JsonPointer $path = null, $i = null) { - $validator = $this->getFactory()->createInstanceFor('type'); + $validator = $this->factory->createInstanceFor('type'); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); @@ -231,8 +176,9 @@ protected function checkType($value, $schema = null, JsonPointer $path = null, $ */ protected function checkUndefined($value, $schema = null, JsonPointer $path = null, $i = null) { - $validator = $this->getFactory()->createInstanceFor('undefined'); - $validator->check($value, $this->schemaStorage->resolveRefSchema($schema), $path, $i); + $validator = $this->factory->createInstanceFor('undefined'); + + $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i); $this->addErrors($validator->getErrors()); } @@ -247,7 +193,7 @@ protected function checkUndefined($value, $schema = null, JsonPointer $path = nu */ protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null) { - $validator = $this->getFactory()->createInstanceFor('string'); + $validator = $this->factory->createInstanceFor('string'); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); @@ -263,7 +209,7 @@ protected function checkString($value, $schema = null, JsonPointer $path = null, */ protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null) { - $validator = $this->getFactory()->createInstanceFor('number'); + $validator = $this->factory->createInstanceFor('number'); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); @@ -279,7 +225,7 @@ protected function checkNumber($value, $schema = null, JsonPointer $path = null, */ protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null) { - $validator = $this->getFactory()->createInstanceFor('enum'); + $validator = $this->factory->createInstanceFor('enum'); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); @@ -295,7 +241,7 @@ protected function checkEnum($value, $schema = null, JsonPointer $path = null, $ */ protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null) { - $validator = $this->getFactory()->createInstanceFor('format'); + $validator = $this->factory->createInstanceFor('format'); $validator->check($value, $schema, $path, $i); $this->addErrors($validator->getErrors()); @@ -308,7 +254,7 @@ protected function checkFormat($value, $schema = null, JsonPointer $path = null, */ protected function getTypeCheck() { - return $this->getFactory()->getTypeCheck(); + return $this->factory->getTypeCheck(); } /** diff --git a/src/JsonSchema/Constraints/EnumConstraint.php b/src/JsonSchema/Constraints/EnumConstraint.php index 23adb653..376d3ee9 100644 --- a/src/JsonSchema/Constraints/EnumConstraint.php +++ b/src/JsonSchema/Constraints/EnumConstraint.php @@ -31,7 +31,7 @@ public function check($element, $schema = null, JsonPointer $path = null, $i = n foreach ($schema->enum as $enum) { $enumType = gettype($enum); - if (($this->checkMode & self::CHECK_MODE_TYPE_CAST) && $type == "array" && $enumType == "object") { + if (($this->factory->getCheckMode() & self::CHECK_MODE_TYPE_CAST) && $type == "array" && $enumType == "object") { if ((object)$element == $enum) { return; } diff --git a/src/JsonSchema/Constraints/Factory.php b/src/JsonSchema/Constraints/Factory.php index 8fd72a83..5eadb17e 100644 --- a/src/JsonSchema/Constraints/Factory.php +++ b/src/JsonSchema/Constraints/Factory.php @@ -129,17 +129,22 @@ public function setConstraintClass($name, $class) */ public function createInstanceFor($constraintName) { - if (array_key_exists($constraintName, $this->constraintMap)) { - if (!isset($this->instanceCache[$constraintName])) { - $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]( - $this->checkMode, - $this->schemaStorage, - $this->uriRetriever, - $this - ); - } - return clone $this->instanceCache[$constraintName]; + if (!isset($this->constraintMap[$constraintName])) { + throw new InvalidArgumentException('Unknown constraint ' . $constraintName); } - throw new InvalidArgumentException('Unknown constraint ' . $constraintName); + + if (!isset($this->instanceCache[$constraintName])) { + $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this); + } + + return clone $this->instanceCache[$constraintName]; + } + + /** + * @return int + */ + public function getCheckMode() + { + return $this->checkMode; } } diff --git a/src/JsonSchema/Constraints/ObjectConstraint.php b/src/JsonSchema/Constraints/ObjectConstraint.php index 07fb46a2..b0008f8e 100644 --- a/src/JsonSchema/Constraints/ObjectConstraint.php +++ b/src/JsonSchema/Constraints/ObjectConstraint.php @@ -82,6 +82,7 @@ public function validatePatternProperties($element, JsonPointer $path = null, $p public function validateElement($element, $matches, $objectDefinition = null, JsonPointer $path = null, $additionalProp = null) { $this->validateMinMaxConstraint($element, $objectDefinition, $path); + foreach ($element as $i => $value) { $definition = $this->getProperty($objectDefinition, $i); @@ -105,7 +106,7 @@ public function validateElement($element, $matches, $objectDefinition = null, Js $this->addError($path, "The presence of the property " . $i . " requires that " . $require . " also be present", 'requires'); } - $property = $this->getProperty($element, $i, new UndefinedConstraint()); + $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined')); if (is_object($property)) { $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path); } @@ -121,17 +122,17 @@ public function validateElement($element, $matches, $objectDefinition = null, Js */ public function validateDefinition($element, $objectDefinition = null, JsonPointer $path = null) { - $default = $this->getFactory()->createInstanceFor('undefined'); + $undefinedConstraint = $this->factory->createInstanceFor('undefined'); foreach ($objectDefinition as $i => $value) { - $property = $this->getProperty($element, $i, $default); + $property = $this->getProperty($element, $i, $undefinedConstraint); $definition = $this->getProperty($objectDefinition, $i); - if($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST){ + if($this->factory->getCheckMode() & Constraint::CHECK_MODE_TYPE_CAST){ if(!($property instanceof Constraint)) { $property = $this->coerce($property, $definition); - if($this->checkMode & Constraint::CHECK_MODE_COERCE) { + if($this->factory->getCheckMode() & Constraint::CHECK_MODE_COERCE) { if (is_object($element)) { $element->{$i} = $property; } else { @@ -228,10 +229,10 @@ protected function coerce($value, $definition) */ protected function getProperty($element, $property, $fallback = null) { - if (is_array($element) /*$this->checkMode == self::CHECK_MODE_TYPE_CAST*/) { - return array_key_exists($property, $element) ? $element[$property] : $fallback; - } elseif (is_object($element)) { - return property_exists($element, $property) ? $element->$property : $fallback; + if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) /*$this->checkMode == self::CHECK_MODE_TYPE_CAST*/) { + return $element[$property]; + } elseif (is_object($element) && property_exists($element, $property)) { + return $element->$property; } return $fallback; diff --git a/src/JsonSchema/Constraints/TypeConstraint.php b/src/JsonSchema/Constraints/TypeConstraint.php index 753585b8..1b2125e0 100644 --- a/src/JsonSchema/Constraints/TypeConstraint.php +++ b/src/JsonSchema/Constraints/TypeConstraint.php @@ -82,7 +82,7 @@ protected function validateTypesArray($value, array $type, &$validTypesWording, // with a new type constraint if (is_object($tp)) { if (!$isValid) { - $validator = $this->getFactory()->createInstanceFor('type'); + $validator = $this->factory->createInstanceFor('type'); $subSchema = new \stdClass(); $subSchema->type = $tp; $validator->check($value, $subSchema, $path, null); diff --git a/src/JsonSchema/Constraints/UndefinedConstraint.php b/src/JsonSchema/Constraints/UndefinedConstraint.php index 71b1afd7..59a8c843 100644 --- a/src/JsonSchema/Constraints/UndefinedConstraint.php +++ b/src/JsonSchema/Constraints/UndefinedConstraint.php @@ -60,7 +60,7 @@ public function validateTypes($value, $schema = null, JsonPointer $path, $i = nu if ($this->getTypeCheck()->isObject($value)) { $this->checkObject( $value, - isset($schema->properties) ? $this->schemaStorage->resolveRefSchema($schema->properties) : $schema, + isset($schema->properties) ? $this->factory->getSchemaStorage()->resolveRefSchema($schema->properties) : $schema, $path, isset($schema->additionalProperties) ? $schema->additionalProperties : null, isset($schema->patternProperties) ? $schema->patternProperties : null @@ -267,7 +267,7 @@ protected function validateDependencies($value, $dependencies, JsonPointer $path protected function validateUri($schema, $schemaUri = null) { $resolver = new UriResolver(); - $retriever = $this->getUriRetriever(); + $retriever = $this->factory->getUriRetriever(); $jsonSchema = null; if ($resolver->isValid($schemaUri)) { diff --git a/src/JsonSchema/Validator.php b/src/JsonSchema/Validator.php index cf147d76..39dca096 100644 --- a/src/JsonSchema/Validator.php +++ b/src/JsonSchema/Validator.php @@ -32,7 +32,7 @@ class Validator extends Constraint */ public function check($value, $schema = null, JsonPointer $path = null, $i = null) { - $validator = $this->getFactory()->createInstanceFor('schema'); + $validator = $this->factory->createInstanceFor('schema'); $validator->check($value, $schema); $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR)); diff --git a/tests/Constraints/BaseTestCase.php b/tests/Constraints/BaseTestCase.php index 0aa34476..5c6dcf18 100644 --- a/tests/Constraints/BaseTestCase.php +++ b/tests/Constraints/BaseTestCase.php @@ -10,6 +10,7 @@ namespace JsonSchema\Tests\Constraints; use JsonSchema\Constraints\Constraint; +use JsonSchema\Constraints\Factory; use JsonSchema\SchemaStorage; use JsonSchema\Uri\UriResolver; use JsonSchema\Validator; @@ -36,7 +37,7 @@ public function testInvalidCases($input, $schema, $checkMode = Constraint::CHECK $schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema))); $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); - $validator = new Validator($checkMode, $schemaStorage); + $validator = new Validator(new Factory($schemaStorage, null, $checkMode)); $validator->check(json_decode($input), $schema); if (array() !== $errors) { @@ -58,7 +59,7 @@ public function testInvalidCasesUsingAssoc($input, $schema, $checkMode = Constra $schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema))); $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); - $validator = new Validator($checkMode, $schemaStorage); + $validator = new Validator(new Factory($schemaStorage, null, $checkMode)); $validator->check(json_decode($input, true), $schema); if (array() !== $errors) { @@ -75,7 +76,7 @@ public function testValidCases($input, $schema, $checkMode = Constraint::CHECK_M $schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema))); $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); - $validator = new Validator($checkMode, $schemaStorage); + $validator = new Validator(new Factory($schemaStorage, null, $checkMode)); $validator->check(json_decode($input), $schema); $this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true)); @@ -95,7 +96,7 @@ public function testValidCasesUsingAssoc($input, $schema, $checkMode = Constrain $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); $value = json_decode($input, true); - $validator = new Validator($checkMode, $schemaStorage); + $validator = new Validator(new Factory($schemaStorage, null, $checkMode)); $validator->check($value, $schema); $this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true)); @@ -142,6 +143,7 @@ protected function getUriRetrieverMock($schema) $uriRetriever->retrieve('http://www.my-domain.com/schema.json') ->willReturn($schema) ->shouldBeCalled(); + $uriRetriever->retrieve(Argument::any()) ->will(function ($args) use ($jsonSchemaDraft03, $jsonSchemaDraft04, $relativeTestsRoot) { if ('http://json-schema.org/draft-03/schema' === $args[0]) { diff --git a/tests/Constraints/CoerciveTest.php b/tests/Constraints/CoerciveTest.php index 7765a78f..bfec165b 100644 --- a/tests/Constraints/CoerciveTest.php +++ b/tests/Constraints/CoerciveTest.php @@ -8,100 +8,102 @@ */ namespace JsonSchema\Tests\Constraints; + use JsonSchema\Constraints\Constraint; +use JsonSchema\Constraints\Factory; use JsonSchema\SchemaStorage; use JsonSchema\Uri\UriResolver; use JsonSchema\Validator; class CoerciveTest extends BasicTypesTest { - /** - * @dataProvider getValidCoerceTests - */ - public function testValidCoerceCasesUsingAssoc($input, $schema) - { - $checkMode = Constraint::CHECK_MODE_COERCE | Constraint::CHECK_MODE_TYPE_CAST; - - $schema = json_decode($schema); - $schemaStorage = new SchemaStorage($this->getUriRetrieverMock($schema), new UriResolver); - $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); - - $value = json_decode($input, true); - $validator = new Validator($checkMode, $schemaStorage); - - $validator->check($value, $schema); - $this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true)); - } - - /** - * @dataProvider getValidCoerceTests - */ - public function testValidCoerceCases($input, $schema, $errors = array()) - { - $checkMode = Constraint::CHECK_MODE_COERCE | Constraint::CHECK_MODE_TYPE_CAST; - - $schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema))); - $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); - - $validator = new Validator($checkMode, $schemaStorage); - $value = json_decode($input); - - $this->assertTrue(gettype($value->number) == "string"); - $this->assertTrue(gettype($value->integer) == "string"); - $this->assertTrue(gettype($value->boolean) == "string"); - - $validator->check($value, $schema); - - $this->assertTrue(gettype($value->number) == "double"); - $this->assertTrue(gettype($value->integer) == "integer"); - $this->assertTrue(gettype($value->boolean) == "boolean"); - - $this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true)); - } - - /** - * @dataProvider getInvalidCoerceTests - */ - public function testInvalidCoerceCases($input, $schema, $errors = array()) - { - $checkMode = Constraint::CHECK_MODE_COERCE | Constraint::CHECK_MODE_TYPE_CAST; - - $schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema))); - $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); - - $validator = new Validator($checkMode, $schemaStorage); - $validator->check(json_decode($input), $schema); - - if (array() !== $errors) { - $this->assertEquals($errors, $validator->getErrors(), print_r($validator->getErrors(),true)); - } - $this->assertFalse($validator->isValid(), print_r($validator->getErrors(), true)); - } - - /** - * @dataProvider getInvalidCoerceTests - */ - public function testInvalidCoerceCasesUsingAssoc($input, $schema, $errors = array()) - { - $checkMode = Constraint::CHECK_MODE_COERCE | Constraint::CHECK_MODE_TYPE_CAST; - - $schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema))); - $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); - - $validator = new Validator($checkMode, $schemaStorage); - $validator->check(json_decode($input, true), $schema); - - if (array() !== $errors) { - $this->assertEquals($errors, $validator->getErrors(), print_r($validator->getErrors(), true)); - } - $this->assertFalse($validator->isValid(), print_r($validator->getErrors(), true)); - } - - public function getValidCoerceTests() - { - return array( - array( - '{ + /** + * @dataProvider getValidCoerceTests + */ + public function testValidCoerceCasesUsingAssoc($input, $schema) + { + $checkMode = Constraint::CHECK_MODE_COERCE | Constraint::CHECK_MODE_TYPE_CAST; + + $schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema))); + $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); + + $validator = new Validator(new Factory($schemaStorage, null, $checkMode)); + + $value = json_decode($input, true); + + $validator->check($value, $schema); + $this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true)); + } + + /** + * @dataProvider getValidCoerceTests + */ + public function testValidCoerceCases($input, $schema, $errors = array()) + { + $checkMode = Constraint::CHECK_MODE_COERCE | Constraint::CHECK_MODE_TYPE_CAST; + + $schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema))); + $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); + + $validator = new Validator(new Factory($schemaStorage, null, $checkMode)); + $value = json_decode($input); + + $this->assertTrue(gettype($value->number) == "string"); + $this->assertTrue(gettype($value->integer) == "string"); + $this->assertTrue(gettype($value->boolean) == "string"); + + $validator->check($value, $schema); + + $this->assertTrue(gettype($value->number) == "double"); + $this->assertTrue(gettype($value->integer) == "integer"); + $this->assertTrue(gettype($value->boolean) == "boolean"); + + $this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true)); + } + + /** + * @dataProvider getInvalidCoerceTests + */ + public function testInvalidCoerceCases($input, $schema, $errors = array()) + { + $checkMode = Constraint::CHECK_MODE_COERCE | Constraint::CHECK_MODE_TYPE_CAST; + + $schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema))); + $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); + + $validator = new Validator(new Factory($schemaStorage, null, $checkMode)); + $validator->check(json_decode($input), $schema); + + if (array() !== $errors) { + $this->assertEquals($errors, $validator->getErrors(), print_r($validator->getErrors(), true)); + } + $this->assertFalse($validator->isValid(), print_r($validator->getErrors(), true)); + } + + /** + * @dataProvider getInvalidCoerceTests + */ + public function testInvalidCoerceCasesUsingAssoc($input, $schema, $errors = array()) + { + $checkMode = Constraint::CHECK_MODE_COERCE | Constraint::CHECK_MODE_TYPE_CAST; + + $schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema))); + $schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json'); + + $validator = new Validator(new Factory($schemaStorage, null, $checkMode)); + $validator->check(json_decode($input, true), $schema); + + if (array() !== $errors) { + $this->assertEquals($errors, $validator->getErrors(), print_r($validator->getErrors(), true)); + } + $this->assertFalse($validator->isValid(), print_r($validator->getErrors(), true)); + } + + public function getValidCoerceTests() + { + return array( + array( + '{ "string":"string test", "number":"1.5", "integer":"1", @@ -117,7 +119,7 @@ public function getValidCoerceTests() "any5": [], "any6": null }', - '{ + '{ "type":"object", "properties":{ "string":{"type":"string"}, @@ -136,100 +138,99 @@ public function getValidCoerceTests() "any6": {"type":"any"} }, "additionalProperties":false - }' - ) - ); - } - + }', + ), + ); + } - public function getInvalidCoerceTests() - { - return array( - array( - '{ + public function getInvalidCoerceTests() + { + return array( + array( + '{ "string":null }', - '{ + '{ "type":"object", "properties": { "string":{"type":"string"} }, "additionalProperties":false - }' - ), - array( - '{ + }', + ), + array( + '{ "number":"five" }', - '{ + '{ "type":"object", "properties": { "number":{"type":"number"} }, "additionalProperties":false - }' - ), - array( - '{ + }', + ), + array( + '{ "integer":"5.2" }', - '{ + '{ "type":"object", "properties": { "integer":{"type":"integer"} }, "additionalProperties":false - }' - ), - array( - '{ + }', + ), + array( + '{ "boolean":"0" }', - '{ + '{ "type":"object", "properties": { "boolean":{"type":"boolean"} }, "additionalProperties":false - }' - ), - array( - '{ + }', + ), + array( + '{ "object":null }', - '{ + '{ "type":"object", "properties": { "object":{"type":"object"} }, "additionalProperties":false - }' - ), - array( - '{ + }', + ), + array( + '{ "array":null }', - '{ + '{ "type":"object", "properties": { "array":{"type":"array"} }, "additionalProperties":false - }' - ), - array( - '{ + }', + ), + array( + '{ "null":1 }', - '{ + '{ "type":"object", "properties": { "null":{"type":"null"} }, "additionalProperties":false - }' - ) - ); - } + }', + ), + ); + } } diff --git a/tests/Constraints/FactoryTest.php b/tests/Constraints/FactoryTest.php index 50a2d69a..956db6de 100644 --- a/tests/Constraints/FactoryTest.php +++ b/tests/Constraints/FactoryTest.php @@ -54,7 +54,6 @@ public function testCreateInstanceForConstraintName($constraintName, $expectedCl $this->assertInstanceOf($expectedClass, $constraint); $this->assertInstanceOf('JsonSchema\Constraints\ConstraintInterface', $constraint); - $this->assertSame($this->factory->getUriRetriever(), $constraint->getUriRetriever()); } public function constraintNameProvider() @@ -114,6 +113,5 @@ public function testSetConstraintClassInstance() $constraint = $this->factory->createInstanceFor('string'); $this->assertInstanceOf('JsonSchema\Tests\Constraints\MyStringConstraint', $constraint); $this->assertInstanceOf('JsonSchema\Constraints\ConstraintInterface', $constraint); - $this->assertSame($this->factory->getUriRetriever(), $constraint->getUriRetriever()); } } diff --git a/tests/Uri/UriRetrieverTest.php b/tests/Uri/UriRetrieverTest.php index d98cebd6..3ac06b6a 100644 --- a/tests/Uri/UriRetrieverTest.php +++ b/tests/Uri/UriRetrieverTest.php @@ -26,7 +26,6 @@ protected function setUp() private function getRetrieverMock($returnSchema, $returnMediaType = Validator::SCHEMA_MEDIA_TYPE) { - $jsonSchema = json_decode($returnSchema); if (JSON_ERROR_NONE < $error = json_last_error()) { @@ -48,13 +47,12 @@ private function getRetrieverMock($returnSchema, $returnMediaType = Validator::S */ public function testChildExtendsParentValidTest($childSchema, $parentSchema) { - $retrieverMock = $this->getRetrieverMock($parentSchema); + $this->mockRetriever($parentSchema); $json = '{"childProp":"infant", "parentProp":false}'; $decodedJson = json_decode($json); $decodedJsonSchema = json_decode($childSchema); - $this->validator->setUriRetriever($retrieverMock); $this->validator->check($decodedJson, $decodedJsonSchema); $this->assertTrue($this->validator->isValid()); } @@ -64,13 +62,12 @@ public function testChildExtendsParentValidTest($childSchema, $parentSchema) */ public function testChildExtendsParentInvalidChildTest($childSchema, $parentSchema) { - $retrieverMock = $this->getRetrieverMock($parentSchema); + $this->mockRetriever($parentSchema); $json = '{"childProp":1, "parentProp":false}'; $decodedJson = json_decode($json); $decodedJsonSchema = json_decode($childSchema); - $this->validator->setUriRetriever($retrieverMock); $this->validator->check($decodedJson, $decodedJsonSchema); $this->assertFalse($this->validator->isValid()); } @@ -80,13 +77,12 @@ public function testChildExtendsParentInvalidChildTest($childSchema, $parentSche */ public function testChildExtendsParentInvalidParentTest($childSchema, $parentSchema) { - $retrieverMock = $this->getRetrieverMock($parentSchema); + $this->mockRetriever($parentSchema); $json = '{"childProp":"infant", "parentProp":1}'; $decodedJson = json_decode($json); $decodedJsonSchema = json_decode($childSchema); - $this->validator->setUriRetriever($retrieverMock); $this->validator->check($decodedJson, $decodedJsonSchema); $this->assertFalse($this->validator->isValid()); } @@ -97,12 +93,12 @@ public function testChildExtendsParentInvalidParentTest($childSchema, $parentSch public function testResolveRelativeUri($childSchema, $parentSchema) { self::setParentSchemaExtendsValue($parentSchema, 'grandparent'); - $retrieverMock = $this->getRetrieverMock($parentSchema); + $this->mockRetriever($parentSchema); + $json = '{"childProp":"infant", "parentProp":false}'; $decodedJson = json_decode($json); $decodedJsonSchema = json_decode($childSchema); - $this->validator->setUriRetriever($retrieverMock); $this->validator->check($decodedJson, $decodedJsonSchema); $this->assertTrue($this->validator->isValid()); } @@ -269,4 +265,17 @@ public function testConfirmMediaTypeThrowsExceptionForUnsupportedTypes() $this->assertEquals(null, $retriever->confirmMediaType($retriever, null)); } + + private function mockRetriever($schema) + { + $retrieverMock = $this->getRetrieverMock($schema); + + $factory = new \ReflectionProperty('JsonSchema\Constraints\Constraint', 'factory'); + $factory->setAccessible(true); + $factory = $factory->getValue($this->validator); + + $retriever = new \ReflectionProperty('JsonSchema\Constraints\Factory', 'uriRetriever'); + $retriever->setAccessible(true); + $retriever->setValue($factory, $retrieverMock); + } }