1
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-08-12 17:13:57 +02:00

[3.1.0] De-crudify the ConfigSchema space; we're starting over again

- Optimize ConfigSchema by removing non-essential runtime data. We can probably optimize even more by collapsing object structures to arrays.
- Removed validation data from ConfigSchema; this will be reimplemented on Interchange
- Implement a sane Interchange composite hierarchy that doesn't use arrays
- Implement StringHash -> Interchange -> ConfigSchema, and rewrite maintenance file to account for this

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1615 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
Edward Z. Yang
2008-03-22 03:55:59 +00:00
parent 93babf0a88
commit ec59062a9d
42 changed files with 440 additions and 1528 deletions

View File

@@ -10,25 +10,17 @@ class HTMLPurifier_ConfigSchema_InterchangeTest extends UnitTestCase
}
public function testAddNamespace() {
$this->interchange->addNamespace($v = array(
'ID' => 'Namespace',
'DESCRIPTION' => 'Bar',
));
$v = new HTMLPurifier_ConfigSchema_Interchange_Namespace();
$v->namespace = 'Namespace';
$this->interchange->addNamespace($v);
$this->assertIdentical($v, $this->interchange->namespaces['Namespace']);
}
public function testAddDirective() {
$this->interchange->addDirective($v = array(
'ID' => 'Namespace.Directive',
'DESCRIPTION' => 'Bar',
));
$v = new HTMLPurifier_ConfigSchema_Interchange_Directive();
$v->id = new HTMLPurifier_ConfigSchema_Interchange_Id('Namespace', 'Directive');
$this->interchange->addDirective($v);
$this->assertIdentical($v, $this->interchange->directives['Namespace.Directive']);
}
public function testValidator() {
$adapter = $this->interchange->getValidatorAdapter();
$this->expectException(new HTMLPurifier_ConfigSchema_Exception('ID must exist'));
$adapter->addDirective(array());
}
}

View File

@@ -1,44 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_InterchangeValidatorTest extends UnitTestCase
{
public function setup() {
generate_mock_once('HTMLPurifier_ConfigSchema_Interchange');
$this->mock = new HTMLPurifier_ConfigSchema_InterchangeMock();
$this->validator = new HTMLPurifier_ConfigSchema_InterchangeValidator($this->mock);
}
protected function makeValidator($expect_params = null) {
generate_mock_once('HTMLPurifier_ConfigSchema_Validator');
$validator = new HTMLPurifier_ConfigSchema_ValidatorMock();
if ($expect_params !== null) $validator->expectOnce('validate', $expect_params);
else $validator->expectNever('validate');
return $validator;
}
public function testAddNamespaceNullValidator() {
$hash = array('ID' => 'Namespace');
$this->mock->expectOnce('addNamespace', array($hash));
$this->validator->addNamespace($hash);
}
public function testAddNamespaceWithValidators() {
$hash = array('ID' => 'Namespace');
$this->validator->addValidator($this->makeValidator(array($hash, $this->mock)));
$this->validator->namespace->addValidator($this->makeValidator(array($hash, $this->mock)));
$this->validator->directive->addValidator($this->makeValidator()); // not called
$this->mock->expectOnce('addNamespace', array($hash));
$this->validator->addNamespace($hash);
}
public function testAddDirectiveWithValidators() {
$hash = array('ID' => 'Namespace.Directive');
$this->validator->addValidator($this->makeValidator(array($hash, $this->mock)));
$this->validator->namespace->addValidator($this->makeValidator()); // not called
$this->validator->directive->addValidator($this->makeValidator(array($hash, $this->mock)));
$this->mock->expectOnce('addDirective', array($hash));
$this->validator->addDirective($hash);
}
}

View File

@@ -1,137 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_StringHashAdapterTest extends UnitTestCase
{
function __construct() {
generate_mock_once('HTMLPurifier_ConfigSchema');
parent::UnitTestCase();
}
function assertAdapt($input, $calls = array()) {
$schema = new HTMLPurifier_ConfigSchemaMock();
$called = array();
foreach ($calls as $signature) {
list($func, $params) = $signature;
if (!isset($called[$func])) $called[$func] = 0;
$schema->expectAt($called[$func]++, $func, $params);
}
$adapter = new HTMLPurifier_ConfigSchema_StringHashAdapter();
$adapter->adapt($input, $schema);
}
function testBasic() {
$this->assertAdapt(
array(
'ID' => 'Namespace.Directive',
'DEFAULT' => "'default' . 'bar'",
'TYPE' => 'string',
'DESCRIPTION' => "Description of default.\n",
),
array(
array('add', array(
'Namespace', 'Directive', 'defaultbar', 'string',
"Description of default.\n"
)),
)
);
}
function testNamespace() {
$this->assertAdapt(
array(
'ID' => 'Namespace',
'DESCRIPTION' => 'Description of namespace',
),
array(
array('addNamespace', array('Namespace', 'Description of namespace')),
)
);
}
function testValueAliases() {
$this->assertAdapt(
array(
'ID' => 'Ns.Dir',
'VALUE-ALIASES' => "
'milk' => 'dairy',
'cheese' => 'dairy',
",
),
array(
array('addValueAliases', array('Ns', 'Dir', array('milk' => 'dairy', 'cheese' => 'dairy'))),
)
);
}
function testAllowedValues() {
$this->assertAdapt(
array(
'ID' => 'Ns.Dir',
'ALLOWED' => "'val1', 'val2'",
),
array(
array('addAllowedValues', array('Ns', 'Dir', array('val1', 'val2'))),
)
);
}
function testAlias() {
$this->assertAdapt(
array(
'ID' => 'Ns.Dir',
'ALIASES' => "Ns.Dir2, Ns2.Dir",
),
array(
array('addAlias', array('Ns', 'Dir2', 'Ns', 'Dir')),
array('addAlias', array('Ns2', 'Dir', 'Ns', 'Dir')),
)
);
}
function testCombo() {
$this->assertAdapt(
array(
'ID' => 'Ns.Dir',
'DEFAULT' => "'val' . '1'",
'TYPE' => 'string',
'DESCRIPTION' => "Description of default.\n",
'VALUE-ALIASES' => "
'milk' => 'val1',
'cheese' => 'val1',
",
'ALLOWED' => "'val1', 'val2'",
'ALIASES' => "Ns.Dir2, Ns2.Dir",
),
array(
array('add', array(
'Ns', 'Dir', 'val1', 'string',
"Description of default.\n"
)),
array('addAllowedValues', array('Ns', 'Dir', array('val1', 'val2'))),
array('addValueAliases', array('Ns', 'Dir', array('milk' => 'val1', 'cheese' => 'val1'))),
array('addAlias', array('Ns', 'Dir2', 'Ns', 'Dir')),
array('addAlias', array('Ns2', 'Dir', 'Ns', 'Dir')),
)
);
}
function testMissingIdError() {
$this->expectError('Missing key ID in string hash');
$this->assertAdapt(array());
}
function testExtraError() {
$this->expectError("String hash key 'FOOBAR' not used by adapter");
$this->assertAdapt(
array(
'ID' => 'Namespace',
'DESCRIPTION' => 'Description of namespace',
'FOOBAR' => 'Extra stuff',
),
array(
array('addNamespace', array('Namespace', 'Description of namespace')),
)
);
}
}

View File

@@ -1,102 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_StringHashReverseAdapterTest extends UnitTestCase
{
function makeSchema() {
$schema = new HTMLPurifier_ConfigSchema();
$schema->addNamespace('Ns', 'Description of ns.');
$schema->addNamespace('Ns2', 'Description of ns2.');
$schema->add('Ns', 'Dir', 'dairy', 'string',
"Description of default.\nThis directive has been available since 1.2.0.");
$schema->addAllowedValues('Ns', 'Dir', array('dairy', 'meat'));
$schema->addValueAliases('Ns', 'Dir', array('milk' => 'dairy', 'cheese' => 'dairy'));
$schema->addAlias('Ns', 'Dir2', 'Ns', 'Dir');
$schema->addAlias('Ns2', 'Dir', 'Ns', 'Dir');
return $schema;
}
function testNamespace() {
$adapter = new HTMLPurifier_ConfigSchema_StringHashReverseAdapter($this->makeSchema());
$result = $adapter->get('Ns');
$expect = array(
'ID' => 'Ns',
'DESCRIPTION' => "Description of ns.",
);
$this->assertIdentical($result, $expect);
}
function testBadNamespace() {
$adapter = new HTMLPurifier_ConfigSchema_StringHashReverseAdapter($this->makeSchema());
$this->expectError("Namespace 'BadNs' doesn't exist in schema");
$adapter->get('BadNs');
}
function testDirective() {
$adapter = new HTMLPurifier_ConfigSchema_StringHashReverseAdapter($this->makeSchema());
$result = $adapter->get('Ns', 'Dir');
$expect = array(
'ID' => 'Ns.Dir',
'TYPE' => 'string',
'VERSION' => '1.2.0',
'DEFAULT' => "'dairy'",
'DESCRIPTION' => "Description of default.\n",
'ALLOWED' => "'dairy', 'meat'",
'VALUE-ALIASES' => "'milk' => 'dairy',\n'cheese' => 'dairy',\n",
'ALIASES' => "Ns.Dir2, Ns2.Dir",
);
$this->assertIdentical($result, $expect);
}
function testBadDirective() {
$adapter = new HTMLPurifier_ConfigSchema_StringHashReverseAdapter($this->makeSchema());
$this->expectError("Directive 'BadNs.BadDir' doesn't exist in schema");
$adapter->get('BadNs', 'BadDir');
}
function assertMethod($func, $input, $expect) {
$adapter = new HTMLPurifier_ConfigSchema_StringHashReverseAdapter($this->makeSchema());
$result = $adapter->$func($input);
$this->assertIdentical($result, $expect);
}
function testExportEmptyHash() {
$this->assertMethod('exportHash', array(), '');
}
function testExportHash() {
$this->assertMethod('exportHash', array('foo' => 'bar'), "'foo' => 'bar',\n");
}
function testExportEmptyLookup() {
$this->assertMethod('exportLookup', array(), '');
}
function testExportSingleLookup() {
$this->assertMethod('exportLookup', array('key' => true), "'key'");
}
function testExportLookup() {
$this->assertMethod('exportLookup', array('key' => true, 'key2' => true, 3 => true), "'key', 'key2', 3");
}
function assertExtraction($desc, $expect_desc, $expect_version) {
$adapter = new HTMLPurifier_ConfigSchema_StringHashReverseAdapter($this->makeSchema());
list($result_desc, $result_version) = $adapter->extractVersion($desc);
$this->assertIdentical($result_desc, $expect_desc);
$this->assertIdentical($result_version, $expect_version);
}
function testExtractSimple() {
$this->assertExtraction("Desc.\nThis directive has been available since 2.0.0.", "Desc.\n", '2.0.0');
}
function testExtractMultiline() {
$this->assertExtraction("Desc.\nThis directive was available\n since 23.4.333.", "Desc.\n", '23.4.333');
}
}

View File

@@ -1,17 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_Validator_AlnumTest extends HTMLPurifier_ConfigSchema_ValidatorHarness
{
public function setup() {
$this->validator = new HTMLPurifier_ConfigSchema_Validator_Alnum('ID');
parent::setup();
}
public function testValidate() {
$this->expectSchemaException('R&D in ID must be alphanumeric');
$arr = array('ID' => 'R&D');
$this->validator->validate($arr, $this->interchange);
}
}

View File

@@ -1,20 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_Validator_CompositeTest extends HTMLPurifier_ConfigSchema_ValidatorHarness
{
public function testValidate() {
$arr = array('ID' => 'RD');
generate_mock_once('HTMLPurifier_ConfigSchema_Validator');
$mock1 = new HTMLPurifier_ConfigSchema_ValidatorMock();
$mock2 = new HTMLPurifier_ConfigSchema_ValidatorMock();
$mock1->expectOnce('validate', array($arr, $this->interchange));
$mock2->expectOnce('validate', array($arr, $this->interchange));
$this->validator->addValidator($mock1);
$this->validator->addValidator($mock2);
$this->validator->validate($arr, $this->interchange);
}
}

View File

@@ -1,17 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_Validator_ExistsTest extends HTMLPurifier_ConfigSchema_ValidatorHarness
{
public function setup() {
$this->validator = new HTMLPurifier_ConfigSchema_Validator_Exists('ID');
parent::setup();
}
public function testValidate() {
$this->expectSchemaException('ID must exist');
$arr = array();
$this->validator->validate($arr, $this->interchange);
}
}

View File

@@ -1,31 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_Validator_IfTest extends HTMLPurifier_ConfigSchema_ValidatorHarness
{
public function setup() {
parent::setup();
generate_mock_once('HTMLPurifier_ConfigSchema_Validator');
}
public function testValidate() {
$arr = array('ID' => 'RD');
$this->validator->setCondition(new HTMLPurifier_ConfigSchema_Validator_Exists('ID'));
$this->validator->setThen($mock1 = new HTMLPurifier_ConfigSchema_ValidatorMock());
$mock1->expectOnce('validate', array($arr, $this->interchange));
$this->validator->setElse($mock2 = new HTMLPurifier_ConfigSchema_ValidatorMock());
$mock2->expectNever('validate');
$this->validator->validate($arr, $this->interchange);
}
public function testValidateConditionIsFalse() {
$arr = array('ID' => 'RD');
$this->validator->setCondition(new HTMLPurifier_ConfigSchema_Validator_Exists('ALTID'));
$this->validator->setThen($mock1 = new HTMLPurifier_ConfigSchema_ValidatorMock());
$mock1->expectNever('validate');
$this->validator->setElse($mock2 = new HTMLPurifier_ConfigSchema_ValidatorMock());
$mock2->expectOnce('validate', array($arr, $this->interchange));
$this->validator->validate($arr, $this->interchange);
}
}

View File

@@ -1,18 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_Validator_NamespaceExistsTest extends HTMLPurifier_ConfigSchema_ValidatorHarness
{
public function testValidateFail() {
$arr = array('_NAMESPACE' => 'Namespace');
$this->expectSchemaException('Cannot define directive for undefined namespace Namespace');
$this->validator->validate($arr, $this->interchange);
}
public function testValidatePass() {
$arr = array('_NAMESPACE' => 'Namespace');
$this->interchange->addNamespace(array('ID' => 'Namespace'));
$this->validator->validate($arr, $this->interchange);
}
}

View File

@@ -1,31 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_Validator_OrTest extends HTMLPurifier_ConfigSchema_ValidatorHarness
{
public function testValidatePass() {
$arr = array('ID' => 'RD');
$this->validator->addValidator(new HTMLPurifier_ConfigSchema_Validator_Alnum('ID'));
// Never called:
$this->validator->addValidator(new HTMLPurifier_ConfigSchema_Validator_Exists('ALT-ID'));
$this->validator->validate($arr, $this->interchange);
}
public function testValidatePassLater() {
$arr = array('ID' => 'RD');
// This one fails:
$this->validator->addValidator(new HTMLPurifier_ConfigSchema_Validator_Exists('ALT-ID'));
// But this one passes:
$this->validator->addValidator(new HTMLPurifier_ConfigSchema_Validator_Alnum('ID'));
$this->validator->validate($arr, $this->interchange);
}
public function testValidateFail() {
$arr = array('ID' => 'RD');
$this->validator->addValidator(new HTMLPurifier_ConfigSchema_Validator_Exists('ALT-ID'));
$this->validator->addValidator(new HTMLPurifier_ConfigSchema_Validator_Exists('FOOBAR'));
$this->expectException('HTMLPurifier_ConfigSchema_Exception');
$this->validator->validate($arr, $this->interchange);
}
}

View File

@@ -1,34 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_Validator_ParseDefaultTest extends HTMLPurifier_ConfigSchema_ValidatorHarness
{
public function testValidate() {
$arr = array(
'ID' => 'N.D',
'DEFAULT' => 'true',
'_TYPE' => 'bool',
'_NULL' => false,
);
$this->validator->validate($arr, $this->interchange);
$this->assertIdentical($arr, array(
'ID' => 'N.D',
'DEFAULT' => 'true',
'_TYPE' => 'bool',
'_NULL' => false,
'_DEFAULT' => true,
));
}
public function testValidateFail() {
$arr = array(
'ID' => 'N.D',
'DEFAULT' => '"asdf"',
'_TYPE' => 'int',
'_NULL' => true,
);
$this->expectSchemaException('Invalid type for default value in N.D: Expected type int, got string');
$this->validator->validate($arr, $this->interchange);
}
}

View File

@@ -1,25 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_Validator_ParseIdTest extends HTMLPurifier_ConfigSchema_ValidatorHarness
{
public function testValidateNamespace() {
$arr = array('ID' => 'Namespace');
$this->validator->validate($arr, $this->interchange);
$this->assertIdentical($arr, array(
'ID' => 'Namespace',
'_NAMESPACE' => 'Namespace'
));
}
public function testValidateDirective() {
$arr = array('ID' => 'Namespace.Directive');
$this->validator->validate($arr, $this->interchange);
$this->assertIdentical($arr, array(
'ID' => 'Namespace.Directive',
'_NAMESPACE' => 'Namespace',
'_DIRECTIVE' => 'Directive'
));
}
}

View File

@@ -1,34 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_Validator_ParseTypeTest extends HTMLPurifier_ConfigSchema_ValidatorHarness
{
public function testValidatePlain() {
$arr = array('ID' => 'N.D', 'TYPE' => 'string');
$this->validator->validate($arr, $this->interchange);
$this->assertIdentical($arr, array(
'ID' => 'N.D',
'TYPE' => 'string',
'_TYPE' => 'string',
'_NULL' => false,
));
}
public function testValidateWithNull() {
$arr = array('ID' => 'N.D', 'TYPE' => 'int/null');
$this->validator->validate($arr, $this->interchange);
$this->assertIdentical($arr, array(
'ID' => 'N.D',
'TYPE' => 'int/null',
'_TYPE' => 'int',
'_NULL' => true,
));
}
public function testValidateInvalidType() {
$arr = array('ID' => 'N.D', 'TYPE' => 'aint/null');
$this->expectSchemaException('Invalid type aint for configuration directive N.D');
$this->validator->validate($arr, $this->interchange);
}
}

View File

@@ -1,20 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_Validator_UniqueTest extends HTMLPurifier_ConfigSchema_ValidatorHarness
{
public function testValidateNamespace() {
$this->interchange->addNamespace(array('ID' => 'Namespace'));
$this->expectSchemaException('Cannot redefine namespace');
$arr = array('ID' => 'Namespace');
$this->validator->validate($arr, $this->interchange);
}
public function testValidateDirective() {
$this->interchange->addDirective(array('ID' => 'Namespace.Directive'));
$this->expectSchemaException('Cannot redefine directive');
$arr = array('ID' => 'Namespace.Directive');
$this->validator->validate($arr, $this->interchange);
}
}

View File

@@ -1,24 +0,0 @@
<?php
class HTMLPurifier_ConfigSchema_ValidatorHarness extends UnitTestCase
{
protected $interchange, $validator;
public function setup() {
$this->interchange = new HTMLPurifier_ConfigSchema_Interchange();
if (empty($this->validator)) {
$class_to_test = substr(get_class($this), 0, -4);
$this->validator = new $class_to_test;
}
}
public function teardown() {
unset($this->validator, $this->interchange);
}
protected function expectSchemaException($msg) {
$this->expectException(new HTMLPurifier_ConfigSchema_Exception($msg));
}
}

View File

@@ -14,63 +14,44 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
}
function test_defineNamespace() {
$this->schema->addNamespace('http', $d = 'This is an internet protocol.');
$this->assertIdentical($this->schema->info_namespace, array(
'http' => new HTMLPurifier_ConfigDef_Namespace($d)
));
$this->schema->addNamespace('http');
$this->assertIdentical($this->schema->info['http'], array());
$this->assertIdentical($this->schema->defaults['http'], array());
}
function test_define() {
$this->schema->addNamespace('Car', 'Automobiles, those gas-guzzlers!');
$this->schema->addNamespace('Car');
$this->schema->add('Car', 'Seats', 5, 'int', $d = 'Standard issue.');
$this->schema->add('Car', 'Seats', 5, 'int', false);
$this->assertIdentical($this->schema->defaults['Car']['Seats'], 5);
$this->assertIdentical($this->schema->info['Car']['Seats'],
new HTMLPurifier_ConfigDef_Directive('int', $d)
new HTMLPurifier_ConfigDef_Directive('int')
);
$this->schema->add('Car', 'Age', null, 'int/null', $d = 'Not always known.');
$this->schema->add('Car', 'Age', null, 'int', true);
$this->assertIdentical($this->schema->defaults['Car']['Age'], null);
$this->assertIdentical($this->schema->info['Car']['Age'],
new HTMLPurifier_ConfigDef_Directive('int', $d, true)
new HTMLPurifier_ConfigDef_Directive('int', true)
);
$this->expectError('Cannot define directive for undefined namespace');
$this->schema->add('Train', 'Cars', 10, 'int', 'Including the caboose.');
$this->expectError('Directive name must be alphanumeric');
$this->schema->add('Car', 'Is it shiny?', true, 'bool', 'Indicates regular waxing.');
$this->expectError('Invalid type for configuration directive');
$this->schema->add('Car', 'Efficiency', 50, 'mpg', 'The higher the better.');
$this->expectError('Default value does not match directive type');
$this->schema->add('Car', 'Producer', 'Ford', 'int', 'ID of the company that made the car.');
$this->expectError('Description must be non-empty');
$this->schema->add('Car', 'ComplexAttribute', 'lawyers', 'istring', null);
}
function test_defineAllowedValues() {
$this->schema->addNamespace('QuantumNumber', 'D');
$this->schema->add('QuantumNumber', 'Spin', 0.5, 'float',
'Spin of particle. Fourth quantum number, represented by s.');
$this->schema->add('QuantumNumber', 'Current', 's', 'string',
'Currently selected quantum number.');
$this->schema->add('QuantumNumber', 'Difficulty', null, 'string/null', $d = 'How hard are the problems?');
$this->schema->add('QuantumNumber', 'Spin', 0.5, 'float', false);
$this->schema->add('QuantumNumber', 'Current', 's', 'string', false);
$this->schema->add('QuantumNumber', 'Difficulty', null, 'string', true);
$this->schema->addAllowedValues( // okay, since default is null
'QuantumNumber', 'Difficulty', array('easy', 'medium', 'hard')
'QuantumNumber', 'Difficulty', array('easy' => true, 'medium' => true, 'hard' => true)
);
$this->assertIdentical($this->schema->defaults['QuantumNumber']['Difficulty'], null);
$this->assertIdentical($this->schema->info['QuantumNumber']['Difficulty'],
new HTMLPurifier_ConfigDef_Directive(
'string',
$d,
true,
array(
'easy' => true,
@@ -80,30 +61,16 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
)
);
$this->expectError('Cannot define allowed values for undefined directive');
$this->schema->addAllowedValues(
'SpaceTime', 'Symmetry', array('time', 'spatial', 'projective')
);
$this->expectError('Cannot define allowed values for directive whose type is not string');
$this->schema->addAllowedValues(
'QuantumNumber', 'Spin', array(0.5, -0.5)
);
$this->expectError('Default value must be in allowed range of variables');
$this->schema->addAllowedValues(
'QuantumNumber', 'Current', array('n', 'l', 'm') // forgot s!
);
}
function test_defineValueAliases() {
$this->schema->addNamespace('Abbrev', 'Stuff on abbreviations.');
$this->schema->add('Abbrev', 'HTH', 'Happy to Help', 'string', $d = 'Three-letters');
$this->schema->add('Abbrev', 'HTH', 'Happy to Help', 'string', false);
$this->schema->addAllowedValues(
'Abbrev', 'HTH', array(
'Happy to Help',
'Hope that Helps',
'HAIL THE HAND!'
'Happy to Help' => true,
'Hope that Helps' => true,
'HAIL THE HAND!' => true,
)
);
$this->schema->addValueAliases(
@@ -122,7 +89,6 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
$this->assertIdentical($this->schema->info['Abbrev']['HTH'],
new HTMLPurifier_ConfigDef_Directive(
'string',
$d,
false,
array(
'Happy to Help' => true,
@@ -137,25 +103,11 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
)
);
$this->expectError('Cannot define alias to value that is not allowed');
$this->schema->addValueAliases(
'Abbrev', 'HTH', array(
'head' => 'Head to Head'
)
);
$this->expectError('Cannot define alias over allowed value');
$this->schema->addValueAliases(
'Abbrev', 'HTH', array(
'Hope that Helps' => 'Happy to Help'
)
);
}
function testAlias() {
$this->schema->addNamespace('Home', 'Sweet home.');
$this->schema->add('Home', 'Rug', 3, 'int', 'ID.');
$this->schema->addNamespace('Home');
$this->schema->add('Home', 'Rug', 3, 'int', false);
$this->schema->addAlias('Home', 'Carpet', 'Home', 'Rug');
$this->assertTrue(!isset($this->schema->defaults['Home']['Carpet']));
@@ -163,21 +115,6 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
new HTMLPurifier_ConfigDef_DirectiveAlias('Home', 'Rug')
);
$this->expectError('Cannot define directive alias in undefined namespace');
$this->schema->addAlias('Store', 'Rug', 'Home', 'Rug');
$this->expectError('Directive name must be alphanumeric');
$this->schema->addAlias('Home', 'R.g', 'Home', 'Rug');
$this->schema->add('Home', 'Rugger', 'Bob Max', 'string', 'Name of.');
$this->expectError('Cannot define alias over directive');
$this->schema->addAlias('Home', 'Rugger', 'Home', 'Rug');
$this->expectError('Cannot define alias to undefined directive');
$this->schema->addAlias('Home', 'Rug2', 'Home', 'Rugavan');
$this->expectError('Cannot define alias to alias');
$this->schema->addAlias('Home', 'Rug2', 'Home', 'Carpet');
}
}

View File

@@ -17,20 +17,17 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
// test functionality based on ConfigSchema
function testNormal() {
$this->schema->addNamespace('Element', 'Chemical substances that cannot be further decomposed');
$this->schema->addNamespace('Element');
$this->schema->add('Element', 'Abbr', 'H', 'string', 'Abbreviation of element name.');
$this->schema->add('Element', 'Name', 'hydrogen', 'istring', 'Full name of atoms.');
$this->schema->add('Element', 'Number', 1, 'int', 'Atomic number, is identity.');
$this->schema->add('Element', 'Mass', 1.00794, 'float', 'Atomic mass.');
$this->schema->add('Element', 'Radioactive', false, 'bool', 'Does it have rapid decay?');
$this->schema->add('Element', 'Isotopes', array(1 => true, 2 => true, 3 => true), 'lookup',
'What numbers of neutrons for this element have been observed?');
$this->schema->add('Element', 'Traits', array('nonmetallic', 'odorless', 'flammable'), 'list',
'What are general properties of the element?');
$this->schema->add('Element', 'IsotopeNames', array(1 => 'protium', 2 => 'deuterium', 3 => 'tritium'), 'hash',
'Lookup hash of neutron counts to formal names.');
$this->schema->add('Element', 'Object', new stdClass(), 'mixed', 'Model representation.');
$this->schema->add('Element', 'Abbr', 'H', 'string', false);
$this->schema->add('Element', 'Name', 'hydrogen', 'istring', false);
$this->schema->add('Element', 'Number', 1, 'int', false);
$this->schema->add('Element', 'Mass', 1.00794, 'float', false);
$this->schema->add('Element', 'Radioactive', false, 'bool', false);
$this->schema->add('Element', 'Isotopes', array(1 => true, 2 => true, 3 => true), 'lookup', false);
$this->schema->add('Element', 'Traits', array('nonmetallic', 'odorless', 'flammable'), 'list', false);
$this->schema->add('Element', 'IsotopeNames', array(1 => 'protium', 2 => 'deuterium', 3 => 'tritium'), 'hash', false);
$this->schema->add('Element', 'Object', new stdClass(), 'mixed', false);
$config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false;
@@ -84,16 +81,18 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
$this->schema->addNamespace('Instrument', 'Of the musical type.');
// case sensitive
$this->schema->add('Instrument', 'Manufacturer', 'Yamaha', 'string', 'Who made it?');
$this->schema->add('Instrument', 'Manufacturer', 'Yamaha', 'string', false);
$this->schema->addAllowedValues('Instrument', 'Manufacturer', array(
'Yamaha', 'Conn-Selmer', 'Vandoren', 'Laubin', 'Buffet', 'other'));
'Yamaha' => true, 'Conn-Selmer' => true, 'Vandoren' => true,
'Laubin' => true, 'Buffet' => true, 'other' => true));
$this->schema->addValueAliases('Instrument', 'Manufacturer', array(
'Selmer' => 'Conn-Selmer'));
// case insensitive
$this->schema->add('Instrument', 'Family', 'woodwind', 'istring', 'What family is it?');
$this->schema->add('Instrument', 'Family', 'woodwind', 'istring', false);
$this->schema->addAllowedValues('Instrument', 'Family', array(
'brass', 'woodwind', 'percussion', 'string', 'keyboard', 'electronic'));
'brass' => true, 'woodwind' => true, 'percussion' => true,
'string' => true, 'keyboard' => true, 'electronic' => true));
$this->schema->addValueAliases('Instrument', 'Family', array(
'synth' => 'electronic'));
@@ -129,9 +128,9 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function testNull() {
$this->schema->addNamespace('ReportCard', 'It is for grades.');
$this->schema->add('ReportCard', 'English', null, 'string/null', 'Grade from English class.');
$this->schema->add('ReportCard', 'Absences', 0, 'int', 'How many times missing from school?');
$this->schema->addNamespace('ReportCard');
$this->schema->add('ReportCard', 'English', null, 'string', false);
$this->schema->add('ReportCard', 'Absences', 0, 'int', false);
$config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false;
@@ -150,8 +149,8 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function testAliases() {
$this->schema->addNamespace('Home', 'Sweet home.');
$this->schema->add('Home', 'Rug', 3, 'int', 'ID.');
$this->schema->addNamespace('Home');
$this->schema->add('Home', 'Rug', 3, 'int', false);
$this->schema->addAlias('Home', 'Carpet', 'Home', 'Rug');
$config = new HTMLPurifier_Config($this->schema);
@@ -171,9 +170,9 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function test_getBatch() {
$this->schema->addNamespace('Variables', 'Changing quantities in equation.');
$this->schema->add('Variables', 'TangentialAcceleration', 'a_tan', 'string', 'In m/s^2');
$this->schema->add('Variables', 'AngularAcceleration', 'alpha', 'string', 'In rad/s^2');
$this->schema->addNamespace('Variables');
$this->schema->add('Variables', 'TangentialAcceleration', 'a_tan', 'string', false);
$this->schema->add('Variables', 'AngularAcceleration', 'alpha', 'string', false);
$config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false;
@@ -196,9 +195,9 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function test_loadIni() {
$this->schema->addNamespace('Shortcut', 'Keyboard shortcuts for commands');
$this->schema->add('Shortcut', 'Copy', 'c', 'istring', 'Copy text');
$this->schema->add('Shortcut', 'Paste', 'v', 'istring', 'Paste clipboard');
$this->schema->add('Shortcut', 'Cut', 'x', 'istring', 'Cut text');
$this->schema->add('Shortcut', 'Copy', 'c', 'istring', false);
$this->schema->add('Shortcut', 'Paste', 'v', 'istring', false);
$this->schema->add('Shortcut', 'Cut', 'x', 'istring', false);
$config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false;
@@ -275,13 +274,11 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function test_loadArray() {
// setup a few dummy namespaces/directives for our testing
$this->schema->addNamespace('Zoo', 'Animals we have.');
$this->schema->add('Zoo', 'Aadvark', 0, 'int', 'Have?');
$this->schema->add('Zoo', 'Boar', 0, 'int', 'Have?');
$this->schema->add('Zoo', 'Camel', 0, 'int', 'Have?');
$this->schema->add(
'Zoo', 'Others', array(), 'list', 'Other animals we have one of.'
);
$this->schema->addNamespace('Zoo');
$this->schema->add('Zoo', 'Aadvark', 0, 'int', false);
$this->schema->add('Zoo', 'Boar', 0, 'int', false);
$this->schema->add('Zoo', 'Camel', 0, 'int', false);
$this->schema->add('Zoo', 'Others', array(), 'list', false);
$config_manual = new HTMLPurifier_Config($this->schema);
$config_loadabbr = new HTMLPurifier_Config($this->schema);
@@ -317,9 +314,9 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function test_create() {
$this->schema->addNamespace('Cake', 'Properties of it.');
$this->schema->add('Cake', 'Sprinkles', 666, 'int', 'Number of.');
$this->schema->add('Cake', 'Flavor', 'vanilla', 'string', 'Flavor of the batter.');
$this->schema->addNamespace('Cake');
$this->schema->add('Cake', 'Sprinkles', 666, 'int', false);
$this->schema->add('Cake', 'Flavor', 'vanilla', 'string', false);
$config = new HTMLPurifier_Config($this->schema);
$config->set('Cake', 'Sprinkles', 42);
@@ -342,8 +339,8 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
// test finalization
$this->schema->addNamespace('Poem', 'Violets are red, roses are blue...');
$this->schema->add('Poem', 'Meter', 'iambic', 'string', 'Rhythm of poem.');
$this->schema->addNamespace('Poem');
$this->schema->add('Poem', 'Meter', 'iambic', 'string', false);
$config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false;
@@ -365,17 +362,17 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function __onlytest_loadArrayFromForm() {
$this->schema->addNamespace('Pancake', 'This should not be user customizable');
$this->schema->add('Pancake', 'Mix', 'buttermilk', 'string', 'Type of pancake mix to use.');
$this->schema->add('Pancake', 'Served', true, 'bool', 'But this is customizable by user.');
$this->schema->addNamespace('Toppings', 'This is user customizable');
$this->schema->add('Toppings', 'Syrup', true, 'bool', 'Absolutely standard!');
$this->schema->add('Toppings', 'Flavor', 'maple', 'string', 'What flavor is the syrup?');
$this->schema->add('Toppings', 'Strawberries', 3, 'int', 'Quite delightful fruit.');
$this->schema->add('Toppings', 'Calories', 2000, 'int/null', 'Some things are best left unknown.');
$this->schema->add('Toppings', 'DefinitionID', null, 'string/null', 'Do not let this be set');
$this->schema->add('Toppings', 'DefinitionRev', 1, 'int', 'Do not let this be set');
$this->schema->add('Toppings', 'Protected', 1, 'int', 'Do not let this be set');
$this->schema->addNamespace('Pancake');
$this->schema->add('Pancake', 'Mix', 'buttermilk', 'string', false);
$this->schema->add('Pancake', 'Served', true, 'bool', false);
$this->schema->addNamespace('Toppings', false);
$this->schema->add('Toppings', 'Syrup', true, 'bool', false);
$this->schema->add('Toppings', 'Flavor', 'maple', 'string', false);
$this->schema->add('Toppings', 'Strawberries', 3, 'int', false);
$this->schema->add('Toppings', 'Calories', 2000, 'int', true);
$this->schema->add('Toppings', 'DefinitionID', null, 'string', true);
$this->schema->add('Toppings', 'DefinitionRev', 1, 'int', false);
$this->schema->add('Toppings', 'Protected', 1, 'int', false);
$get = array(
'breakfast' => array(
@@ -426,16 +423,16 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
}
function test_getAllowedDirectivesForForm() {
$this->schema->addNamespace('Unused', 'Not mentioned, so deny');
$this->schema->add('Unused', 'Unused', 'Foobar', 'string', 'Not mentioned, do not allow');
$this->schema->addNamespace('Partial', 'Some are mentioned, allow only those');
$this->schema->add('Partial', 'Allowed', true, 'bool', 'Mentioned, allowed');
$this->schema->add('Partial', 'Unused', 'Foobar', 'string', 'Not mentioned, do not allow');
$this->schema->addNamespace('All', 'Entire namespace allowed, allow all unless...');
$this->schema->add('All', 'Allowed', true, 'bool', 'Not mentioned, allowed');
$this->schema->add('All', 'Blacklisted', 'Foobar', 'string', 'Specifically blacklisted');
$this->schema->add('All', 'DefinitionID', 'Foobar', 'string/null', 'Special case, auto-blacklisted');
$this->schema->add('All', 'DefinitionRev', 2, 'int', 'Special case, auto-blacklisted');
$this->schema->addNamespace('Unused');
$this->schema->add('Unused', 'Unused', 'Foobar', 'string', false);
$this->schema->addNamespace('Partial');
$this->schema->add('Partial', 'Allowed', true, 'bool', false);
$this->schema->add('Partial', 'Unused', 'Foobar', 'string', false);
$this->schema->addNamespace('All');
$this->schema->add('All', 'Allowed', true, 'bool', false);
$this->schema->add('All', 'Blacklisted', 'Foobar', 'string', false); // explicitly blacklisted
$this->schema->add('All', 'DefinitionID', 'Foobar', 'string', true); // auto-blacklisted
$this->schema->add('All', 'DefinitionRev', 2, 'int', false); // auto-blacklisted
$input = array('Partial.Allowed', 'All', '-All.Blacklisted');
$output = HTMLPurifier_Config::getAllowedDirectivesForForm($input, $this->schema);