0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2024-12-22 16:31:53 +00:00

[3.1.0] Land PHPT integration (currently required; we'll relax this later)

- Port ConfigSchema and Config tests to new syntax
- Deprecate Debugger
- Add $schema params to most Config convenience functions
- Add --php flag to testing scripts for command line
- NOT TESTED WITH MULTITEST.PHP!


git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1551 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
Edward Z. Yang 2008-02-16 00:40:30 +00:00
parent e28d39e46b
commit 3441421e8b
13 changed files with 275 additions and 137 deletions

9
NEWS
View File

@ -25,8 +25,12 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
be found in extras/. Specifically, these are FSTools and ConfigSchema. be found in extras/. Specifically, these are FSTools and ConfigSchema.
You may find a use for these in your own project, but right now they You may find a use for these in your own project, but right now they
are highly experimental and volatile. are highly experimental and volatile.
! Integration with PHPT allows for automated smoketests
- Autoclose now operates iteratively, i.e. <span><span><div> now has - Autoclose now operates iteratively, i.e. <span><span><div> now has
both span tags closed. both span tags closed.
- Various HTMLPurifier_Config convenience functions now accept another parameter
$schema which defines what HTMLPurifier_ConfigSchema to use besides the
global default.
. Plugins now get their own changelogs according to project conventions. . Plugins now get their own changelogs according to project conventions.
. Convert tokens to use instanceof, reducing memory footprint and . Convert tokens to use instanceof, reducing memory footprint and
improving comparison speed. improving comparison speed.
@ -41,6 +45,11 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
. HTMLPurifier_Token subclasses split into seperate files . HTMLPurifier_Token subclasses split into seperate files
. HTMLPURIFIER_PREFIX now is defined in Bootstrap.php, NOT HTMLPurifier.php . HTMLPURIFIER_PREFIX now is defined in Bootstrap.php, NOT HTMLPurifier.php
. HTMLPURIFIER_PREFIX can now be defined outside of HTML Purifier . HTMLPURIFIER_PREFIX can now be defined outside of HTML Purifier
. New --php=php flag added, allows PHP executable to be specified (command
line only!)
. htmlpurifier_add_test() preferred method to translate test files in to
classes, because it handles PHPT files too.
. Debugger class is deprecated and will be removed soon.
3.0.0, released 2008-01-06 3.0.0, released 2008-01-06
# HTML Purifier is PHP 5 only! The 2.1.x branch will be maintained # HTML Purifier is PHP 5 only! The 2.1.x branch will be maintained

View File

@ -78,14 +78,19 @@ class HTMLPurifier_Config
* object. Can be: a HTMLPurifier_Config() object, * object. Can be: a HTMLPurifier_Config() object,
* an array of directives based on loadArray(), * an array of directives based on loadArray(),
* or a string filename of an ini file. * or a string filename of an ini file.
* @param HTMLPurifier_ConfigSchema Schema object
* @return Configured HTMLPurifier_Config object * @return Configured HTMLPurifier_Config object
*/ */
public static function create($config) { public static function create($config, $schema = null) {
if ($config instanceof HTMLPurifier_Config) { if ($config instanceof HTMLPurifier_Config) {
// pass-through // pass-through
return $config; return $config;
} }
if (!$schema) {
$ret = HTMLPurifier_Config::createDefault(); $ret = HTMLPurifier_Config::createDefault();
} else {
$ret = new HTMLPurifier_Config($schema);
}
if (is_string($config)) $ret->loadIni($config); if (is_string($config)) $ret->loadIni($config);
elseif (is_array($config)) $ret->loadArray($config); elseif (is_array($config)) $ret->loadArray($config);
return $ret; return $ret;
@ -346,8 +351,10 @@ class HTMLPurifier_Config
* namespaces/directives list. * namespaces/directives list.
* @param $allowed List of allowed namespaces/directives * @param $allowed List of allowed namespaces/directives
*/ */
public static function getAllowedDirectivesForForm($allowed) { public static function getAllowedDirectivesForForm($allowed, $schema = null) {
if (!$schema) {
$schema = HTMLPurifier_ConfigSchema::instance(); $schema = HTMLPurifier_ConfigSchema::instance();
}
if ($allowed !== true) { if ($allowed !== true) {
if (is_string($allowed)) $allowed = array($allowed); if (is_string($allowed)) $allowed = array($allowed);
$allowed_ns = array(); $allowed_ns = array();
@ -389,10 +396,11 @@ class HTMLPurifier_Config
* @param $index Index/name that the config variables are in * @param $index Index/name that the config variables are in
* @param $allowed List of allowed namespaces/directives * @param $allowed List of allowed namespaces/directives
* @param $mq_fix Boolean whether or not to enable magic quotes fix * @param $mq_fix Boolean whether or not to enable magic quotes fix
* @param $schema Instance of HTMLPurifier_ConfigSchema to use, if not global copy
*/ */
public static function loadArrayFromForm($array, $index, $allowed = true, $mq_fix = true) { public static function loadArrayFromForm($array, $index, $allowed = true, $mq_fix = true, $schema = null) {
$ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix); $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $schema);
$config = HTMLPurifier_Config::create($ret); $config = HTMLPurifier_Config::create($ret, $schema);
return $config; return $config;
} }
@ -401,7 +409,7 @@ class HTMLPurifier_Config
* @note Same parameters as loadArrayFromForm * @note Same parameters as loadArrayFromForm
*/ */
public function mergeArrayFromForm($array, $index, $allowed = true, $mq_fix = true) { public function mergeArrayFromForm($array, $index, $allowed = true, $mq_fix = true) {
$ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix); $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $this->def);
$this->loadArray($ret); $this->loadArray($ret);
} }
@ -409,11 +417,11 @@ class HTMLPurifier_Config
* Prepares an array from a form into something usable for the more * Prepares an array from a form into something usable for the more
* strict parts of HTMLPurifier_Config * strict parts of HTMLPurifier_Config
*/ */
public static function prepareArrayFromForm($array, $index, $allowed = true, $mq_fix = true) { public static function prepareArrayFromForm($array, $index, $allowed = true, $mq_fix = true, $schema = null) {
$array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array(); $array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array();
$mq = get_magic_quotes_gpc() && $mq_fix; $mq = get_magic_quotes_gpc() && $mq_fix;
$allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed); $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $schema);
$ret = array(); $ret = array();
foreach ($allowed as $key) { foreach ($allowed as $key) {
list($ns, $directive) = $key; list($ns, $directive) = $key;

View File

@ -2,10 +2,6 @@
require_once 'HTMLPurifier/ConfigSchema.php'; require_once 'HTMLPurifier/ConfigSchema.php';
if (!class_exists('CS')) {
class CS extends HTMLPurifier_ConfigSchema {}
}
class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
{ {

View File

@ -2,46 +2,39 @@
require_once 'HTMLPurifier/Config.php'; require_once 'HTMLPurifier/Config.php';
if (!class_exists('CS')) {
class CS extends HTMLPurifier_ConfigSchema {}
}
class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
{ {
protected $our_copy, $old_copy; protected $schema;
function setUp() { function setUp() {
// set up a dummy schema object for testing // set up a dummy schema object for testing
$our_copy = new HTMLPurifier_ConfigSchema(); $this->schema = new HTMLPurifier_ConfigSchema();
$this->old_copy = HTMLPurifier_ConfigSchema::instance();
$this->our_copy =& HTMLPurifier_ConfigSchema::instance($our_copy);
} }
function tearDown() { function tearDown() {
HTMLPurifier_ConfigSchema::instance($this->old_copy);
tally_errors($this); tally_errors($this);
} }
// test functionality based on ConfigSchema // test functionality based on ConfigSchema
function testNormal() { function testNormal() {
CS::defineNamespace('Element', 'Chemical substances that cannot be further decomposed'); $this->schema->addNamespace('Element', 'Chemical substances that cannot be further decomposed');
CS::define('Element', 'Abbr', 'H', 'string', 'Abbreviation of element name.'); $this->schema->add('Element', 'Abbr', 'H', 'string', 'Abbreviation of element name.');
CS::define('Element', 'Name', 'hydrogen', 'istring', 'Full name of atoms.'); $this->schema->add('Element', 'Name', 'hydrogen', 'istring', 'Full name of atoms.');
CS::define('Element', 'Number', 1, 'int', 'Atomic number, is identity.'); $this->schema->add('Element', 'Number', 1, 'int', 'Atomic number, is identity.');
CS::define('Element', 'Mass', 1.00794, 'float', 'Atomic mass.'); $this->schema->add('Element', 'Mass', 1.00794, 'float', 'Atomic mass.');
CS::define('Element', 'Radioactive', false, 'bool', 'Does it have rapid decay?'); $this->schema->add('Element', 'Radioactive', false, 'bool', 'Does it have rapid decay?');
CS::define('Element', 'Isotopes', array(1 => true, 2 => true, 3 => true), 'lookup', $this->schema->add('Element', 'Isotopes', array(1 => true, 2 => true, 3 => true), 'lookup',
'What numbers of neutrons for this element have been observed?'); 'What numbers of neutrons for this element have been observed?');
CS::define('Element', 'Traits', array('nonmetallic', 'odorless', 'flammable'), 'list', $this->schema->add('Element', 'Traits', array('nonmetallic', 'odorless', 'flammable'), 'list',
'What are general properties of the element?'); 'What are general properties of the element?');
CS::define('Element', 'IsotopeNames', array(1 => 'protium', 2 => 'deuterium', 3 => 'tritium'), 'hash', $this->schema->add('Element', 'IsotopeNames', array(1 => 'protium', 2 => 'deuterium', 3 => 'tritium'), 'hash',
'Lookup hash of neutron counts to formal names.'); 'Lookup hash of neutron counts to formal names.');
CS::define('Element', 'Object', new stdClass(), 'mixed', 'Model representation.'); $this->schema->add('Element', 'Object', new stdClass(), 'mixed', 'Model representation.');
$config = HTMLPurifier_Config::createDefault(); $config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false; $config->autoFinalize = false;
// test default value retrieval // test default value retrieval
@ -90,23 +83,23 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function testEnumerated() { function testEnumerated() {
CS::defineNamespace('Instrument', 'Of the musical type.'); $this->schema->addNamespace('Instrument', 'Of the musical type.');
// case sensitive // case sensitive
CS::define('Instrument', 'Manufacturer', 'Yamaha', 'string', 'Who made it?'); $this->schema->add('Instrument', 'Manufacturer', 'Yamaha', 'string', 'Who made it?');
CS::defineAllowedValues('Instrument', 'Manufacturer', array( $this->schema->addAllowedValues('Instrument', 'Manufacturer', array(
'Yamaha', 'Conn-Selmer', 'Vandoren', 'Laubin', 'Buffet', 'other')); 'Yamaha', 'Conn-Selmer', 'Vandoren', 'Laubin', 'Buffet', 'other'));
CS::defineValueAliases('Instrument', 'Manufacturer', array( $this->schema->addValueAliases('Instrument', 'Manufacturer', array(
'Selmer' => 'Conn-Selmer')); 'Selmer' => 'Conn-Selmer'));
// case insensitive // case insensitive
CS::define('Instrument', 'Family', 'woodwind', 'istring', 'What family is it?'); $this->schema->add('Instrument', 'Family', 'woodwind', 'istring', 'What family is it?');
CS::defineAllowedValues('Instrument', 'Family', array( $this->schema->addAllowedValues('Instrument', 'Family', array(
'brass', 'woodwind', 'percussion', 'string', 'keyboard', 'electronic')); 'brass', 'woodwind', 'percussion', 'string', 'keyboard', 'electronic'));
CS::defineValueAliases('Instrument', 'Family', array( $this->schema->addValueAliases('Instrument', 'Family', array(
'synth' => 'electronic')); 'synth' => 'electronic'));
$config = HTMLPurifier_Config::createDefault(); $config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false; $config->autoFinalize = false;
// case sensitive // case sensitive
@ -138,11 +131,11 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function testNull() { function testNull() {
CS::defineNamespace('ReportCard', 'It is for grades.'); $this->schema->addNamespace('ReportCard', 'It is for grades.');
CS::define('ReportCard', 'English', null, 'string/null', 'Grade from English class.'); $this->schema->add('ReportCard', 'English', null, 'string/null', 'Grade from English class.');
CS::define('ReportCard', 'Absences', 0, 'int', 'How many times missing from school?'); $this->schema->add('ReportCard', 'Absences', 0, 'int', 'How many times missing from school?');
$config = HTMLPurifier_Config::createDefault(); $config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false; $config->autoFinalize = false;
$config->set('ReportCard', 'English', 'B-'); $config->set('ReportCard', 'English', 'B-');
@ -159,11 +152,11 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function testAliases() { function testAliases() {
CS::defineNamespace('Home', 'Sweet home.'); $this->schema->addNamespace('Home', 'Sweet home.');
CS::define('Home', 'Rug', 3, 'int', 'ID.'); $this->schema->add('Home', 'Rug', 3, 'int', 'ID.');
CS::defineAlias('Home', 'Carpet', 'Home', 'Rug'); $this->schema->addAlias('Home', 'Carpet', 'Home', 'Rug');
$config = HTMLPurifier_Config::createDefault(); $config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false; $config->autoFinalize = false;
$this->assertIdentical($config->get('Home', 'Rug'), 3); $this->assertIdentical($config->get('Home', 'Rug'), 3);
@ -180,11 +173,11 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function test_getBatch() { function test_getBatch() {
CS::defineNamespace('Variables', 'Changing quantities in equation.'); $this->schema->addNamespace('Variables', 'Changing quantities in equation.');
CS::define('Variables', 'TangentialAcceleration', 'a_tan', 'string', 'In m/s^2'); $this->schema->add('Variables', 'TangentialAcceleration', 'a_tan', 'string', 'In m/s^2');
CS::define('Variables', 'AngularAcceleration', 'alpha', 'string', 'In rad/s^2'); $this->schema->add('Variables', 'AngularAcceleration', 'alpha', 'string', 'In rad/s^2');
$config = HTMLPurifier_Config::createDefault(); $config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false; $config->autoFinalize = false;
// grab a namespace // grab a namespace
@ -204,12 +197,12 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function test_loadIni() { function test_loadIni() {
CS::defineNamespace('Shortcut', 'Keyboard shortcuts for commands'); $this->schema->addNamespace('Shortcut', 'Keyboard shortcuts for commands');
CS::define('Shortcut', 'Copy', 'c', 'istring', 'Copy text'); $this->schema->add('Shortcut', 'Copy', 'c', 'istring', 'Copy text');
CS::define('Shortcut', 'Paste', 'v', 'istring', 'Paste clipboard'); $this->schema->add('Shortcut', 'Paste', 'v', 'istring', 'Paste clipboard');
CS::define('Shortcut', 'Cut', 'x', 'istring', 'Cut text'); $this->schema->add('Shortcut', 'Cut', 'x', 'istring', 'Cut text');
$config = HTMLPurifier_Config::createDefault(); $config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false; $config->autoFinalize = false;
$config->loadIni(dirname(__FILE__) . '/ConfigTest-loadIni.ini'); $config->loadIni(dirname(__FILE__) . '/ConfigTest-loadIni.ini');
@ -225,8 +218,6 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
// we actually want to use the old copy, because the definition // we actually want to use the old copy, because the definition
// generation routines have dependencies on configuration values // generation routines have dependencies on configuration values
$this->old_copy = HTMLPurifier_ConfigSchema::instance($this->old_copy);
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();
$config->set('HTML', 'Doctype', 'XHTML 1.0 Strict'); $config->set('HTML', 'Doctype', 'XHTML 1.0 Strict');
$config->autoFinalize = false; $config->autoFinalize = false;
@ -264,41 +255,39 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
} }
function test_getHTMLDefinition_rawError() { function test_getHTMLDefinition_rawError() {
$this->old_copy = HTMLPurifier_ConfigSchema::instance($this->old_copy);
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();
$this->expectError('Cannot retrieve raw version without specifying %HTML.DefinitionID'); $this->expectError('Cannot retrieve raw version without specifying %HTML.DefinitionID');
$def =& $config->getHTMLDefinition(true); $def =& $config->getHTMLDefinition(true);
} }
function test_getCSSDefinition() { function test_getCSSDefinition() {
$this->old_copy = HTMLPurifier_ConfigSchema::instance($this->old_copy);
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();
$def = $config->getCSSDefinition(); $def = $config->getCSSDefinition();
$this->assertIsA($def, 'HTMLPurifier_CSSDefinition'); $this->assertIsA($def, 'HTMLPurifier_CSSDefinition');
} }
function test_getDefinition() { function test_getDefinition() {
CS::defineNamespace('Cache', 'Cache stuff'); $this->schema->addNamespace('Cache', 'Cache stuff');
CS::define('Cache', 'DefinitionImpl', null, 'string/null', 'Cache?'); $this->schema->add('Cache', 'DefinitionImpl', null, 'string/null', 'Cache?');
CS::defineNamespace('Crust', 'Krusty Krabs'); $this->schema->addNamespace('Crust', 'Krusty Krabs');
$config = HTMLPurifier_Config::createDefault(); $config = new HTMLPurifier_Config($this->schema);
$this->expectError("Definition of Crust type not supported"); $this->expectError("Definition of Crust type not supported");
$config->getDefinition('Crust'); $config->getDefinition('Crust');
} }
function test_loadArray() { function test_loadArray() {
// setup a few dummy namespaces/directives for our testing // setup a few dummy namespaces/directives for our testing
CS::defineNamespace('Zoo', 'Animals we have.'); $this->schema->addNamespace('Zoo', 'Animals we have.');
CS::define('Zoo', 'Aadvark', 0, 'int', 'Have?'); $this->schema->add('Zoo', 'Aadvark', 0, 'int', 'Have?');
CS::define('Zoo', 'Boar', 0, 'int', 'Have?'); $this->schema->add('Zoo', 'Boar', 0, 'int', 'Have?');
CS::define('Zoo', 'Camel', 0, 'int', 'Have?'); $this->schema->add('Zoo', 'Camel', 0, 'int', 'Have?');
CS::define( $this->schema->add(
'Zoo', 'Others', array(), 'list', 'Other animals we have one of.' 'Zoo', 'Others', array(), 'list', 'Other animals we have one of.'
); );
$config_manual = HTMLPurifier_Config::createDefault(); $config_manual = new HTMLPurifier_Config($this->schema);
$config_loadabbr = HTMLPurifier_Config::createDefault(); $config_loadabbr = new HTMLPurifier_Config($this->schema);
$config_loadfull = HTMLPurifier_Config::createDefault(); $config_loadfull = new HTMLPurifier_Config($this->schema);
$config_manual->set('Zoo', 'Aadvark', 3); $config_manual->set('Zoo', 'Aadvark', 3);
$config_manual->set('Zoo', 'Boar', 5); $config_manual->set('Zoo', 'Boar', 5);
@ -330,23 +319,23 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
function test_create() { function test_create() {
CS::defineNamespace('Cake', 'Properties of it.'); $this->schema->addNamespace('Cake', 'Properties of it.');
CS::define('Cake', 'Sprinkles', 666, 'int', 'Number of.'); $this->schema->add('Cake', 'Sprinkles', 666, 'int', 'Number of.');
CS::define('Cake', 'Flavor', 'vanilla', 'string', 'Flavor of the batter.'); $this->schema->add('Cake', 'Flavor', 'vanilla', 'string', 'Flavor of the batter.');
$config = HTMLPurifier_Config::createDefault(); $config = new HTMLPurifier_Config($this->schema);
$config->set('Cake', 'Sprinkles', 42); $config->set('Cake', 'Sprinkles', 42);
// test flat pass-through // test flat pass-through
$created_config = HTMLPurifier_Config::create($config); $created_config = HTMLPurifier_Config::create($config, $this->schema);
$this->assertIdentical($config, $created_config); $this->assertIdentical($config, $created_config);
// test loadArray // test loadArray
$created_config = HTMLPurifier_Config::create(array('Cake.Sprinkles' => 42)); $created_config = HTMLPurifier_Config::create(array('Cake.Sprinkles' => 42), $this->schema);
$this->assertIdentical($config, $created_config); $this->assertIdentical($config, $created_config);
// test loadIni // test loadIni
$created_config = HTMLPurifier_Config::create(dirname(__FILE__) . '/ConfigTest-create.ini'); $created_config = HTMLPurifier_Config::create(dirname(__FILE__) . '/ConfigTest-create.ini', $this->schema);
$this->assertIdentical($config, $created_config); $this->assertIdentical($config, $created_config);
} }
@ -355,10 +344,10 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
// test finalization // test finalization
CS::defineNamespace('Poem', 'Violets are red, roses are blue...'); $this->schema->addNamespace('Poem', 'Violets are red, roses are blue...');
CS::define('Poem', 'Meter', 'iambic', 'string', 'Rhythm of poem.'); $this->schema->add('Poem', 'Meter', 'iambic', 'string', 'Rhythm of poem.');
$config = HTMLPurifier_Config::createDefault(); $config = new HTMLPurifier_Config($this->schema);
$config->autoFinalize = false; $config->autoFinalize = false;
$config->set('Poem', 'Meter', 'irregular'); $config->set('Poem', 'Meter', 'irregular');
@ -376,19 +365,19 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
} }
function test_loadArrayFromForm() { function __onlytest_loadArrayFromForm() {
CS::defineNamespace('Pancake', 'This should not be user customizable'); $this->schema->addNamespace('Pancake', 'This should not be user customizable');
CS::define('Pancake', 'Mix', 'buttermilk', 'string', 'Type of pancake mix to use.'); $this->schema->add('Pancake', 'Mix', 'buttermilk', 'string', 'Type of pancake mix to use.');
CS::define('Pancake', 'Served', true, 'bool', 'But this is customizable by user.'); $this->schema->add('Pancake', 'Served', true, 'bool', 'But this is customizable by user.');
CS::defineNamespace('Toppings', 'This is user customizable'); $this->schema->addNamespace('Toppings', 'This is user customizable');
CS::define('Toppings', 'Syrup', true, 'bool', 'Absolutely standard!'); $this->schema->add('Toppings', 'Syrup', true, 'bool', 'Absolutely standard!');
CS::define('Toppings', 'Flavor', 'maple', 'string', 'What flavor is the syrup?'); $this->schema->add('Toppings', 'Flavor', 'maple', 'string', 'What flavor is the syrup?');
CS::define('Toppings', 'Strawberries', 3, 'int', 'Quite delightful fruit.'); $this->schema->add('Toppings', 'Strawberries', 3, 'int', 'Quite delightful fruit.');
CS::define('Toppings', 'Calories', 2000, 'int/null', 'Some things are best left unknown.'); $this->schema->add('Toppings', 'Calories', 2000, 'int/null', 'Some things are best left unknown.');
CS::define('Toppings', 'DefinitionID', null, 'string/null', 'Do not let this be set'); $this->schema->add('Toppings', 'DefinitionID', null, 'string/null', 'Do not let this be set');
CS::define('Toppings', 'DefinitionRev', 1, 'int', 'Do not let this be set'); $this->schema->add('Toppings', 'DefinitionRev', 1, 'int', 'Do not let this be set');
CS::define('Toppings', 'Protected', 1, 'int', 'Do not let this be set'); $this->schema->add('Toppings', 'Protected', 1, 'int', 'Do not let this be set');
$get = array( $get = array(
'breakfast' => array( 'breakfast' => array(
@ -411,9 +400,14 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
'Toppings.Flavor' => "juice", 'Toppings.Flavor' => "juice",
'Toppings.Strawberries' => 999, 'Toppings.Strawberries' => 999,
'Toppings.Calories' => null 'Toppings.Calories' => null
)); ), $this->schema);
$config_result = HTMLPurifier_Config::loadArrayFromForm($get, 'breakfast', array('Pancake.Served', 'Toppings', '-Toppings.Protected')); $config_result = HTMLPurifier_Config::loadArrayFromForm(
$get, 'breakfast',
array('Pancake.Served', 'Toppings', '-Toppings.Protected'),
true, // mq fix
$this->schema
);
$this->assertEqual($config_expect, $config_result); $this->assertEqual($config_expect, $config_result);
@ -434,19 +428,19 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
} }
function test_getAllowedDirectivesForForm() { function test_getAllowedDirectivesForForm() {
CS::defineNamespace('Unused', 'Not mentioned, so deny'); $this->schema->addNamespace('Unused', 'Not mentioned, so deny');
CS::define('Unused', 'Unused', 'Foobar', 'string', 'Not mentioned, do not allow'); $this->schema->add('Unused', 'Unused', 'Foobar', 'string', 'Not mentioned, do not allow');
CS::defineNamespace('Partial', 'Some are mentioned, allow only those'); $this->schema->addNamespace('Partial', 'Some are mentioned, allow only those');
CS::define('Partial', 'Allowed', true, 'bool', 'Mentioned, allowed'); $this->schema->add('Partial', 'Allowed', true, 'bool', 'Mentioned, allowed');
CS::define('Partial', 'Unused', 'Foobar', 'string', 'Not mentioned, do not allow'); $this->schema->add('Partial', 'Unused', 'Foobar', 'string', 'Not mentioned, do not allow');
CS::defineNamespace('All', 'Entire namespace allowed, allow all unless...'); $this->schema->addNamespace('All', 'Entire namespace allowed, allow all unless...');
CS::define('All', 'Allowed', true, 'bool', 'Not mentioned, allowed'); $this->schema->add('All', 'Allowed', true, 'bool', 'Not mentioned, allowed');
CS::define('All', 'Blacklisted', 'Foobar', 'string', 'Specifically blacklisted'); $this->schema->add('All', 'Blacklisted', 'Foobar', 'string', 'Specifically blacklisted');
CS::define('All', 'DefinitionID', 'Foobar', 'string/null', 'Special case, auto-blacklisted'); $this->schema->add('All', 'DefinitionID', 'Foobar', 'string/null', 'Special case, auto-blacklisted');
CS::define('All', 'DefinitionRev', 2, 'int', 'Special case, auto-blacklisted'); $this->schema->add('All', 'DefinitionRev', 2, 'int', 'Special case, auto-blacklisted');
$input = array('Partial.Allowed', 'All', '-All.Blacklisted'); $input = array('Partial.Allowed', 'All', '-All.Blacklisted');
$output = HTMLPurifier_Config::getAllowedDirectivesForForm($input); $output = HTMLPurifier_Config::getAllowedDirectivesForForm($input, $this->schema);
$expect = array( $expect = array(
array('Partial', 'Allowed'), array('Partial', 'Allowed'),
array('All', 'Allowed') array('All', 'Allowed')

View File

@ -63,7 +63,6 @@ class HTMLPurifier_GeneratorTest extends HTMLPurifier_ComplexHarness
foreach ($inputs as $i => $input) { foreach ($inputs as $i => $input) {
$result = $this->obj->generateFromToken($input); $result = $this->obj->generateFromToken($input);
$this->assertIdentical($result, $expect[$i]); $this->assertIdentical($result, $expect[$i]);
paintIf($result, $result != $expect[$i]);
} }
} }
@ -92,7 +91,6 @@ class HTMLPurifier_GeneratorTest extends HTMLPurifier_ComplexHarness
foreach ($inputs as $i => $input) { foreach ($inputs as $i => $input) {
$result = $this->obj->generateAttributes($input, 'irrelevant'); $result = $this->obj->generateAttributes($input, 'irrelevant');
$this->assertIdentical($result, $expect[$i]); $this->assertIdentical($result, $expect[$i]);
paintIf($result, $result != $expect[$i]);
} }
} }

View File

@ -71,7 +71,6 @@ class HTMLPurifier_Lexer_DirectLexTest extends HTMLPurifier_Harness
for($i = 0; $i < $size; $i++) { for($i = 0; $i < $size; $i++) {
$result = $this->DirectLex->parseAttributeString($input[$i], $config, $context); $result = $this->DirectLex->parseAttributeString($input[$i], $config, $context);
$this->assertIdentical($expect[$i], $result, 'Test ' . $i . ': %s'); $this->assertIdentical($expect[$i], $result, 'Test ' . $i . ': %s');
paintIf($result, $expect[$i] != $result);
} }
} }

View File

@ -0,0 +1,6 @@
--TEST--
PHPT testing framework smoketest
--FILE--
Foobar
--EXPECT--
Foobar

View File

@ -0,0 +1,28 @@
<?php
/**
* Controller for PHPT that implements the SimpleTest unit-testing interface.
*/
class PHPT_Controller_SimpleTest extends SimpleTestCase
{
protected $_path;
public function __construct($path) {
$this->_path = $path;
parent::SimpleTestCase($path);
}
public function testPhpt() {
if (is_dir($this->_path)) {
$factory = new PHPT_Suite_Factory();
$suite = $factory->factory($this->_path, true);
} else {
$suite = new PHPT_Suite(array($this->_path));
}
// Adapter class that relays messages to SimpleTest
$phpt_reporter = new PHPT_Reporter_SimpleTest($this->_reporter);
$suite->run($phpt_reporter);
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* Proxies results from PHPT_Reporter to SimpleTest's reporter
*/
class PHPT_Reporter_SimpleTest implements PHPT_Reporter
{
/** SimpleTest reporter to proxy results to */
protected $reporter;
/** @param SimpleTest reporter */
public function __construct($reporter) {
$this->reporter = $reporter;
}
/**
* Called when the Reporter is started from a PHPT_Suite
* @todo Figure out if Suites can be named
*/
public function onSuiteStart(PHPT_Suite $suite) {
$this->reporter->paintGroupStart('PHPT Suite', $suite->count());
}
/**
* Called when the Reporter is finished in a PHPT_Suite
*/
public function onSuiteEnd(PHPT_Suite $suite) {
$this->reporter->paintGroupEnd('PHPT Suite');
}
/**
* Called when a Case is started
*/
public function onCaseStart(PHPT_Case $case) {
$this->reporter->paintCaseStart($case->name);
}
/**
* Called when a Case ends
*/
public function onCaseEnd(PHPT_Case $case) {
$this->reporter->paintCaseEnd($case->name);
}
/**
* Called when a Case runs without Exception
*/
public function onCasePass(PHPT_Case $case) {
$this->reporter->paintPass("{$case->name} in {$case->filename}");
}
/**
* Called when a PHPT_Case_VetoException is thrown during a Case's run()
*/
public function onCaseSkip(PHPT_Case $case, PHPT_Case_VetoException $veto) {
$this->reporter->paintSkip("{$case->name} in {$case->filename}");
}
/**
* Called when any Exception other than a PHPT_Case_VetoException is encountered
* during a Case's run()
*/
public function onCaseFail(PHPT_Case $case, PHPT_Case_FailureException $failure) {
$this->reporter->paintFail($failure->getReason());
}
public function onParserError(Exception $exception) {
$this->reporter->paintException($exception);
}
}

View File

@ -5,6 +5,20 @@ if (!defined('HTMLPurifierTest')) {
exit; exit;
} }
// setup our own autoload, checking for HTMLPurifier library if spl_autoload_register
// is not allowed
function __autoload($class) {
if (!function_exists('spl_autoload_register')) {
if (HTMLPurifier_Bootstrap::autoload($class)) return true;
if (HTMLPurifierExtras::autoload($class)) return true;
}
require_once str_replace('_', '/', $class) . '.php';
return true;
}
if (function_exists('spl_autoload_register')) {
spl_autoload_register('__autoload');
}
// default settings (protect against register_globals) // default settings (protect against register_globals)
$GLOBALS['HTMLPurifierTest'] = array(); $GLOBALS['HTMLPurifierTest'] = array();
$GLOBALS['HTMLPurifierTest']['PEAR'] = false; // do PEAR tests $GLOBALS['HTMLPurifierTest']['PEAR'] = false; // do PEAR tests
@ -43,10 +57,7 @@ if ( is_string($GLOBALS['HTMLPurifierTest']['PEAR']) ) {
// after external libraries are loaded, turn on compile time errors // after external libraries are loaded, turn on compile time errors
error_reporting(E_ALL | E_STRICT); error_reporting(E_ALL | E_STRICT);
// load SimpleTest addons // load SimpleTest addon functions
require_once 'HTMLPurifier/SimpleTest/Reporter.php';
require_once 'CliTestCase.php';
require_once 'Debugger.php';
require_once 'generate_mock_once.func.php'; require_once 'generate_mock_once.func.php';
require_once 'path2class.func.php'; require_once 'path2class.func.php';
require_once 'tally_errors.func.php'; // compat require_once 'tally_errors.func.php'; // compat
@ -104,3 +115,17 @@ function htmlpurifier_args(&$AC, $aliases, $o, $v) {
if (is_string($AC[$o])) $AC[$o] = $v; if (is_string($AC[$o])) $AC[$o] = $v;
if (is_bool($AC[$o])) $AC[$o] = true; if (is_bool($AC[$o])) $AC[$o] = true;
} }
/**
* Adds a test-class; depending on the file's extension this may involve
* a regular UnitTestCase or a special PHPT test
*/
function htmlpurifier_add_test($test, $test_file) {
$info = pathinfo($test_file);
if (!isset($info['extension']) || $info['extension'] == 'phpt') {
$test->addTestCase(new PHPT_Controller_SimpleTest($test_file));
} else {
require_once $test_file;
$test->addTestClass(path2class($test_file));
}
}

View File

@ -25,22 +25,22 @@ $AC['standalone'] = false;
$AC['file'] = ''; $AC['file'] = '';
$AC['xml'] = false; $AC['xml'] = false;
$AC['dry'] = false; $AC['dry'] = false;
$AC['php'] = 'php';
$aliases = array( $aliases = array(
'f' => 'file', 'f' => 'file',
); );
htmlpurifier_parse_args($AC, $aliases); htmlpurifier_parse_args($AC, $aliases);
// clean out cache if necessary if (!SimpleReporter::inCli()) {
if ($AC['flush']) shell_exec('php ../maintenance/flush-definition-cache.php'); // Undo any dangerous parameters
$AC['php'] = 'php';
}
// setup our own autoload for earlier PHP versions $phpt = PHPT_Registry::getInstance();
if (!function_exists('spl_autoload_register')) { $phpt->php = $AC['php'];
function __autoload($class) {
return // we're using the fact that once one OR is true, the rest is skipped // clean out cache if necessary
HTMLPurifier_Bootstrap::autoload($class) || if ($AC['flush']) shell_exec($AC['php'] . ' ../maintenance/flush-definition-cache.php');
HTMLPurifierExtras::autoload($class);
}
}
// initialize and load alternative classes // initialize and load alternative classes
require_once '../extras/HTMLPurifierExtras.auto.php'; require_once '../extras/HTMLPurifierExtras.auto.php';
@ -81,8 +81,7 @@ if ($AC['file']) {
if ($AC['file']) { if ($AC['file']) {
$test = new TestSuite($AC['file']); $test = new TestSuite($AC['file']);
require_once $AC['file']; htmlpurifier_add_test($test, $AC['file']);
$test->addTestClass(path2class($AC['file']));
} else { } else {
@ -90,8 +89,7 @@ if ($AC['file']) {
if ($AC['standalone']) $standalone = ' (standalone)'; if ($AC['standalone']) $standalone = ' (standalone)';
$test = new TestSuite('All HTML Purifier tests on PHP ' . PHP_VERSION . $standalone); $test = new TestSuite('All HTML Purifier tests on PHP ' . PHP_VERSION . $standalone);
foreach ($test_files as $test_file) { foreach ($test_files as $test_file) {
require_once $test_file; htmlpurifier_add_test($test, $test_file);
$test->addTestClass(path2class($test_file));
} }
} }

View File

@ -37,6 +37,7 @@ $AC['exclude-standalone'] = false;
$AC['file'] = ''; $AC['file'] = '';
$AC['xml'] = false; $AC['xml'] = false;
$AC['quiet'] = false; $AC['quiet'] = false;
$AC['php'] = 'php';
$aliases = array( $aliases = array(
'f' => 'file', 'f' => 'file',
'q' => 'quiet', 'q' => 'quiet',
@ -44,11 +45,11 @@ $aliases = array(
htmlpurifier_parse_args($AC, $aliases); htmlpurifier_parse_args($AC, $aliases);
// Calls generate-includes.php automatically // Calls generate-includes.php automatically
shell_exec("php ../maintenance/merge-library.php"); shell_exec($AC['php'] . ' ../maintenance/merge-library.php');
// Not strictly necessary, but its a good idea // Not strictly necessary, but its a good idea
shell_exec("php ../maintenance/generate-schema-cache.php"); shell_exec($AC['php'] . ' ../maintenance/generate-schema-cache.php');
shell_exec('php ../maintenance/flush-definition-cache.php'); shell_exec($AC['php'] . ' ../maintenance/flush-definition-cache.php');
$test = new TestSuite('HTML Purifier Multiple Versions Test'); $test = new TestSuite('HTML Purifier Multiple Versions Test');
$file = ''; $file = '';
@ -73,8 +74,8 @@ foreach ($versions_to_test as $version) {
$version = $version[0]; $version = $version[0];
$flush = '--flush'; $flush = '--flush';
} }
if (!$AC['exclude-normal']) $test->addTestCase(new CliTestCase("$phpv $version index.php --xml $flush $file", $AC['quiet'], $size)); if (!$AC['exclude-normal']) $test->addTestCase(new CliTestCase("$phpv $version index.php --xml $flush --php=\"$phpv $version\" $file", $AC['quiet'], $size));
if (!$AC['exclude-standalone']) $test->addTestCase(new CliTestCase("$phpv $version index.php --xml --standalone $file", $AC['quiet'], $size)); if (!$AC['exclude-standalone']) $test->addTestCase(new CliTestCase("$phpv $version index.php --xml --standalone --php=\"$phpv $version\" $file", $AC['quiet'], $size));
} }
// This is the HTML Purifier website's test XML file. We could // This is the HTML Purifier website's test XML file. We could
@ -88,4 +89,4 @@ if ($AC['xml']) {
} }
$test->run($reporter); $test->run($reporter);
shell_exec('php ../maintenance/flush-definition-cache.php'); shell_exec($AC['php'] . ' ../maintenance/flush-definition-cache.php');

View File

@ -140,3 +140,7 @@ $test_files[] = 'ConfigSchema/StringHashAdapterTest.php';
$test_files[] = 'ConfigSchema/StringHashReverseAdapterTest.php'; $test_files[] = 'ConfigSchema/StringHashReverseAdapterTest.php';
$test_files[] = 'ConfigSchema/StringHashParserTest.php'; $test_files[] = 'ConfigSchema/StringHashParserTest.php';
$test_files[] = 'ConfigSchema/StringHashTest.php'; $test_files[] = 'ConfigSchema/StringHashTest.php';
// PHPT tests
$test_files[] = 'HTMLPurifier/PHPT';