Commit 463fd530 authored by alexpott's avatar alexpott

Issue #2270815 by vijaycs85, Gábor Hojtsy, nvinayvinay: Make schema testing...

Issue #2270815 by vijaycs85, Gábor Hojtsy, nvinayvinay: Make schema testing code available as generic API.
parent f39f2c27
...@@ -2,26 +2,22 @@ ...@@ -2,26 +2,22 @@
/** /**
* @file * @file
* Contains Drupal\config\Tests\ConfigSchemaTestBase. * Contains \Drupal\Core\Config\Schema\SchemaCheckTrait.
*/ */
namespace Drupal\config\Tests; namespace Drupal\Core\Config\Schema;
use Drupal\Core\Config\Schema\ArrayElement;
use Drupal\Core\Config\TypedConfigManagerInterface; use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\TypedData\PrimitiveInterface;
use Drupal\Core\TypedData\Type\BooleanInterface; use Drupal\Core\TypedData\Type\BooleanInterface;
use Drupal\Core\TypedData\Type\StringInterface; use Drupal\Core\TypedData\Type\StringInterface;
use Drupal\Component\Utility\String;
use Drupal\Core\Config\Schema\SchemaIncompleteException;
use Drupal\Core\TypedData\PrimitiveInterface;
use Drupal\Core\TypedData\Type\FloatInterface; use Drupal\Core\TypedData\Type\FloatInterface;
use Drupal\Core\TypedData\Type\IntegerInterface; use Drupal\Core\TypedData\Type\IntegerInterface;
use Drupal\simpletest\WebTestBase;
/** /**
* Provides a base class to help test configuration schema. * Provides a trait for checking configuration schema.
*/ */
abstract class ConfigSchemaTestBase extends WebTestBase { trait SchemaCheckTrait {
/** /**
* The config schema wrapper object for the configuration object under test. * The config schema wrapper object for the configuration object under test.
...@@ -38,14 +34,7 @@ abstract class ConfigSchemaTestBase extends WebTestBase { ...@@ -38,14 +34,7 @@ abstract class ConfigSchemaTestBase extends WebTestBase {
protected $configName; protected $configName;
/** /**
* Global state for whether the config has a valid schema. * Checks the TypedConfigManager has a valid schema for the configuration.
*
* @var boolean
*/
protected $configPass;
/**
* Asserts the TypedConfigManager has a valid schema for the configuration.
* *
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
* The TypedConfigManager. * The TypedConfigManager.
...@@ -53,22 +42,25 @@ abstract class ConfigSchemaTestBase extends WebTestBase { ...@@ -53,22 +42,25 @@ abstract class ConfigSchemaTestBase extends WebTestBase {
* The configuration name. * The configuration name.
* @param array $config_data * @param array $config_data
* The configuration data. * The configuration data.
*
* @return array|bool
* FALSE if no schema found. List of errors if any found. TRUE if fully
* valid.
*/ */
public function assertConfigSchema(TypedConfigManagerInterface $typed_config, $config_name, $config_data) { public function checkConfigSchema(TypedConfigManagerInterface $typed_config, $config_name, $config_data) {
$this->configName = $config_name; $this->configName = $config_name;
if (!$typed_config->hasConfigSchema($config_name)) { if (!$typed_config->hasConfigSchema($config_name)) {
$this->fail(String::format('No schema for !config_name', array('!config_name' => $config_name))); return FALSE;
return;
} }
$definition = $typed_config->getDefinition($config_name); $definition = $typed_config->getDefinition($config_name);
$this->schema = $typed_config->create($definition, $config_data); $this->schema = $typed_config->create($definition, $config_data);
$this->configPass = TRUE;
foreach ($config_data as $key => $value) { foreach ($config_data as $key => $value) {
$this->checkValue($key, $value); $errors = $this->checkValue($key, $value);
} }
if ($this->configPass) { if (empty($errors)) {
$this->pass(String::format('Schema found for !config_name and values comply with schema.', array('!config_name' => $config_name))); return TRUE;
} }
return $errors;
} }
/** /**
...@@ -79,25 +71,26 @@ public function assertConfigSchema(TypedConfigManagerInterface $typed_config, $c ...@@ -79,25 +71,26 @@ public function assertConfigSchema(TypedConfigManagerInterface $typed_config, $c
* @param mixed $value * @param mixed $value
* Value of given key. * Value of given key.
* *
* @return mixed * @return array
* Returns mixed value. * List of errors found while checking with the corresponding schema.
*/ */
protected function checkValue($key, $value) { protected function checkValue($key, $value) {
$error_key = $this->configName . ':' . $key;
$element = FALSE; $element = FALSE;
try { try {
$element = $this->schema->get($key); $element = $this->schema->get($key);
} }
catch (SchemaIncompleteException $e) { catch (SchemaIncompleteException $e) {
if (is_scalar($value) || $value === NULL) { if (is_scalar($value) || $value === NULL) {
$this->fail("{$this->configName}:$key has no schema."); return array($error_key => 'Missing schema.');
} }
} }
// Do not check value if it is defined to be ignored. // Do not check value if it is defined to be ignored.
if ($element && $element instanceof Ignore) { if ($element && $element instanceof Ignore) {
return $value; return array();
} }
if (is_scalar($value) || $value === NULL) { if ($element && is_scalar($value) || $value === NULL) {
$success = FALSE; $success = FALSE;
$type = gettype($value); $type = gettype($value);
if ($element instanceof PrimitiveInterface) { if ($element instanceof PrimitiveInterface) {
...@@ -111,12 +104,13 @@ protected function checkValue($key, $value) { ...@@ -111,12 +104,13 @@ protected function checkValue($key, $value) {
} }
$class = get_class($element); $class = get_class($element);
if (!$success) { if (!$success) {
$this->fail("{$this->configName}:$key has the wrong schema. Variable type is $type and schema class is $class."); return array($error_key => "Variable type is $type but applied schema class is $class.");
} }
} }
else { else {
$errors = array();
if (!$element instanceof ArrayElement) { if (!$element instanceof ArrayElement) {
$this->fail("Non-scalar {$this->configName}:$key is not defined as an array type (such as mapping or sequence)."); $errors[$error_key] = 'Non-scalar value but not defined as an array (such as mapping or sequence)';
} }
// Go on processing so we can get errors on all levels. Any non-scalar // Go on processing so we can get errors on all levels. Any non-scalar
...@@ -126,18 +120,11 @@ protected function checkValue($key, $value) { ...@@ -126,18 +120,11 @@ protected function checkValue($key, $value) {
} }
// Recurse into any nested keys. // Recurse into any nested keys.
foreach ($value as $nested_value_key => $nested_value) { foreach ($value as $nested_value_key => $nested_value) {
$value[$nested_value_key] = $this->checkValue($key . '.' . $nested_value_key, $nested_value); $errors = array_merge($errors, $this->checkValue($key . '.' . $nested_value_key, $nested_value));
} }
return $errors;
} }
return $value; // No errors found.
} return array();
/**
* {@inheritdoc}
*/
protected function fail($message = NULL, $group = 'Other') {
$this->configPass = FALSE;
return parent::fail($message, $group);
} }
} }
...@@ -8,12 +8,15 @@ ...@@ -8,12 +8,15 @@
namespace Drupal\block\Tests; namespace Drupal\block\Tests;
use Drupal\block\Entity\Block; use Drupal\block\Entity\Block;
use Drupal\config\Tests\ConfigSchemaTestBase; use Drupal\config\Tests\SchemaCheckTestTrait;
use Drupal\simpletest\WebTestBase;
/** /**
* Tests the block config schema. * Tests the block config schema.
*/ */
class BlockConfigSchemaTest extends ConfigSchemaTestBase { class BlockConfigSchemaTest extends WebTestBase {
use SchemaCheckTestTrait;
/** /**
* {@inheritdoc} * {@inheritdoc}
......
...@@ -7,12 +7,15 @@ ...@@ -7,12 +7,15 @@
namespace Drupal\color\Tests; namespace Drupal\color\Tests;
use Drupal\config\Tests\ConfigSchemaTestBase; use Drupal\config\Tests\SchemaCheckTestTrait;
use Drupal\simpletest\WebTestBase;
/** /**
* Tests the Color config schema. * Tests the Color config schema.
*/ */
class ColorConfigSchemaTest extends ConfigSchemaTestBase { class ColorConfigSchemaTest extends WebTestBase {
use SchemaCheckTestTrait;
/** /**
* Modules to enable. * Modules to enable.
......
...@@ -10,11 +10,14 @@ ...@@ -10,11 +10,14 @@
use Drupal\config_test\TestInstallStorage; use Drupal\config_test\TestInstallStorage;
use Drupal\Core\Config\InstallStorage; use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\TypedConfigManager; use Drupal\Core\Config\TypedConfigManager;
use Drupal\simpletest\WebTestBase;
/** /**
* Tests default configuration availability and type with configuration schema. * Tests default configuration availability and type with configuration schema.
*/ */
class DefaultConfigTest extends ConfigSchemaTestBase { class DefaultConfigTest extends WebTestBase {
use SchemaCheckTestTrait;
/** /**
* Modules to enable. * Modules to enable.
......
<?php
/**
* @file
* Contains Drupal\config\Tests\SchemaCheckTestTrait.
*/
namespace Drupal\config\Tests;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\Config\Schema\SchemaCheckTrait;
use Drupal\Component\Utility\String;
/**
* Provides a class for checking configuration schema.
*/
trait SchemaCheckTestTrait {
use SchemaCheckTrait;
/**
* Asserts the TypedConfigManager has a valid schema for the configuration.
*
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
* The TypedConfigManager.
* @param string $config_name
* The configuration name.
* @param array $config_data
* The configuration data.
*/
public function assertConfigSchema(TypedConfigManagerInterface $typed_config, $config_name, $config_data) {
$errors = $this->checkConfigSchema($typed_config, $config_name, $config_data);
if ($errors === FALSE) {
// @todo Since the use of this trait is under TestBase, it works.
// Can be fixed as part of https://drupal.org/node/2260053.
$this->fail(String::format('No schema for !config_name', array('!config_name' => $config_name)));
return;
}
elseif ($errors === TRUE) {
// @todo Since the use of this trait is under TestBase, it works.
// Can be fixed as part of https://drupal.org/node/2260053.
$this->pass(String::format('Schema found for !config_name and values comply with schema.', array('!config_name' => $config_name)));
}
else {
foreach ($errors as $key => $error) {
// @todo Since the use of this trait is under TestBase, it works.
// Can be fixed as part of https://drupal.org/node/2260053.
$this->fail($key . ': ' . $error);
}
}
}
}
...@@ -7,12 +7,15 @@ ...@@ -7,12 +7,15 @@
namespace Drupal\language\Tests; namespace Drupal\language\Tests;
use Drupal\config\Tests\ConfigSchemaTestBase; use Drupal\config\Tests\SchemaCheckTestTrait;
use Drupal\simpletest\WebTestBase;
/** /**
* Tests the language config schema. * Tests the language config schema.
*/ */
class LanguageConfigSchemaTest extends ConfigSchemaTestBase { class LanguageConfigSchemaTest extends WebTestBase {
use SchemaCheckTestTrait;
/** /**
* Modules to enable. * Modules to enable.
......
...@@ -7,12 +7,15 @@ ...@@ -7,12 +7,15 @@
namespace Drupal\user\Tests; namespace Drupal\user\Tests;
use Drupal\config\Tests\ConfigSchemaTestBase; use Drupal\config\Tests\SchemaCheckTestTrait;
use Drupal\simpletest\WebTestBase;
/** /**
* Tests the User action config schema. * Tests the User action config schema.
*/ */
class UserActionConfigSchemaTest extends ConfigSchemaTestBase { class UserActionConfigSchemaTest extends WebTestBase {
use SchemaCheckTestTrait;
/** /**
* Modules to enable. * Modules to enable.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment