mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2025-08-05 21:57:26 +02:00
Fix two bugs with caching of customized raw definitions.
The first bug is that we will repeatedly write out the result of a customized raw definition to the filesystem, even when a cache entry already exists. The second bug is that caching these definitions doesn't actually work (the cache entry is written but never used.) A new API for retrieving raw definitions permits the user to take advantage of caching. Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
This commit is contained in:
@@ -18,8 +18,6 @@ class HTMLPurifier_AttrValidator_ErrorsTest extends HTMLPurifier_ErrorsHarness
|
||||
}
|
||||
|
||||
function testAttributesTransformedGlobalPre() {
|
||||
$this->config->set('HTML.DefinitionID',
|
||||
'HTMLPurifier_AttrValidator_ErrorsTest::testAttributesTransformedGlobalPre');
|
||||
$def = $this->config->getHTMLDefinition(true);
|
||||
generate_mock_once('HTMLPurifier_AttrTransform');
|
||||
$transform = new HTMLPurifier_AttrTransformMock();
|
||||
|
@@ -4,6 +4,7 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
|
||||
{
|
||||
|
||||
protected $schema;
|
||||
protected $oldFactory;
|
||||
|
||||
public function setUp() {
|
||||
// set up a dummy schema object for testing
|
||||
@@ -230,23 +231,58 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
|
||||
$this->assertNotEqual($def, $old_def);
|
||||
$this->assertTrue($def->setup);
|
||||
|
||||
// test retrieval of raw definition
|
||||
}
|
||||
|
||||
function test_getHTMLDefinition_deprecatedRawError() {
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$config->chatty = false;
|
||||
// test deprecated retrieval of raw definition
|
||||
$config->set('HTML.DefinitionID', 'HTMLPurifier_ConfigTest->test_getHTMLDefinition()');
|
||||
$config->set('HTML.DefinitionRev', 3);
|
||||
$this->expectError("Useless DefinitionID declaration");
|
||||
$def = $config->getHTMLDefinition(true);
|
||||
$this->assertNotEqual($def, $old_def);
|
||||
$this->assertEqual(false, $def->setup);
|
||||
|
||||
// auto initialization
|
||||
$config->getHTMLDefinition();
|
||||
$this->assertTrue($def->setup);
|
||||
}
|
||||
|
||||
function test_getHTMLDefinition_optimizedRawError() {
|
||||
$this->expectException(new HTMLPurifier_Exception("Cannot set optimized = true when raw = false"));
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$config->getHTMLDefinition(false, true);
|
||||
}
|
||||
|
||||
function test_getHTMLDefinition_rawAfterSetupError() {
|
||||
$this->expectException(new HTMLPurifier_Exception("Cannot retrieve raw definition after it has already been setup"));
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$config->chatty = false;
|
||||
$config->getHTMLDefinition();
|
||||
$config->getHTMLDefinition(true);
|
||||
}
|
||||
|
||||
function test_getHTMLDefinition_inconsistentOptimizedError() {
|
||||
$this->expectError("Useless DefinitionID declaration");
|
||||
$this->expectException(new HTMLPurifier_Exception("Inconsistent use of optimized and unoptimized raw definition retrievals"));
|
||||
$config = HTMLPurifier_Config::create(array('HTML.DefinitionID' => 'HTMLPurifier_ConfigTest->test_getHTMLDefinition_inconsistentOptimizedError'));
|
||||
$config->chatty = false;
|
||||
$config->getHTMLDefinition(true, false);
|
||||
$config->getHTMLDefinition(true, true);
|
||||
}
|
||||
|
||||
function test_getHTMLDefinition_inconsistentOptimizedError2() {
|
||||
$this->expectException(new HTMLPurifier_Exception("Inconsistent use of optimized and unoptimized raw definition retrievals"));
|
||||
$config = HTMLPurifier_Config::create(array('HTML.DefinitionID' => 'HTMLPurifier_ConfigTest->test_getHTMLDefinition_inconsistentOptimizedError2'));
|
||||
$config->chatty = false;
|
||||
$config->getHTMLDefinition(true, true);
|
||||
$config->getHTMLDefinition(true, false);
|
||||
}
|
||||
|
||||
function test_getHTMLDefinition_rawError() {
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$this->expectException(new HTMLPurifier_Exception('Cannot retrieve raw version without specifying %HTML.DefinitionID'));
|
||||
$def = $config->getHTMLDefinition(true);
|
||||
$def = $config->getHTMLDefinition(true, true);
|
||||
}
|
||||
|
||||
function test_getCSSDefinition() {
|
||||
@@ -458,6 +494,64 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
|
||||
$this->assertIdentical($config, $config2);
|
||||
}
|
||||
|
||||
function testDefinitionCachingNothing() {
|
||||
list($mock, $config) = $this->setupCacheMock('HTML');
|
||||
// should not touch the cache
|
||||
$mock->expectNever('get');
|
||||
$mock->expectNever('add');
|
||||
$mock->expectNever('set');
|
||||
$config->getDefinition('HTML', true);
|
||||
$config->getDefinition('HTML', true);
|
||||
$config->getDefinition('HTML');
|
||||
$this->teardownCacheMock();
|
||||
}
|
||||
|
||||
function testDefinitionCachingOptimized() {
|
||||
list($mock, $config) = $this->setupCacheMock('HTML');
|
||||
$mock->expectNever('set');
|
||||
$config->set('HTML.DefinitionID', 'HTMLPurifier_ConfigTest->testDefinitionCachingOptimized');
|
||||
$mock->expectOnce('get');
|
||||
$mock->setReturnValue('get', null);
|
||||
$this->assertTrue($config->maybeGetRawHTMLDefinition());
|
||||
$this->assertTrue($config->maybeGetRawHTMLDefinition());
|
||||
$mock->expectOnce('add');
|
||||
$config->getDefinition('HTML');
|
||||
$this->teardownCacheMock();
|
||||
}
|
||||
|
||||
function testDefinitionCachingOptimizedHit() {
|
||||
$fake_config = HTMLPurifier_Config::createDefault();
|
||||
$fake_def = $fake_config->getHTMLDefinition();
|
||||
list($mock, $config) = $this->setupCacheMock('HTML');
|
||||
// should never frob cache
|
||||
$mock->expectNever('add');
|
||||
$mock->expectNever('set');
|
||||
$config->set('HTML.DefinitionID', 'HTMLPurifier_ConfigTest->testDefinitionCachingOptimizedHit');
|
||||
$mock->expectOnce('get');
|
||||
$mock->setReturnValue('get', $fake_def);
|
||||
$this->assertNull($config->maybeGetRawHTMLDefinition());
|
||||
$config->getDefinition('HTML');
|
||||
$config->getDefinition('HTML');
|
||||
$this->teardownCacheMock();
|
||||
}
|
||||
|
||||
protected function setupCacheMock($type) {
|
||||
// inject our definition cache mock globally (borrowed from
|
||||
// DefinitionFactoryTest)
|
||||
generate_mock_once("HTMLPurifier_DefinitionCacheFactory");
|
||||
$factory = new HTMLPurifier_DefinitionCacheFactoryMock();
|
||||
$this->oldFactory = HTMLPurifier_DefinitionCacheFactory::instance();
|
||||
HTMLPurifier_DefinitionCacheFactory::instance($factory);
|
||||
generate_mock_once("HTMLPurifier_DefinitionCache");
|
||||
$mock = new HTMLPurifier_DefinitionCacheMock();
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$factory->setReturnValue('create', $mock, array($type, $config));
|
||||
return array($mock, $config);
|
||||
}
|
||||
protected function teardownCacheMock() {
|
||||
HTMLPurifier_DefinitionCacheFactory::instance($this->oldFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -172,6 +172,7 @@ class HTMLPurifier_DefinitionCache_SerializerTest extends HTMLPurifier_Definitio
|
||||
* Asserts that a file does not exist, ignoring the stat cache
|
||||
*/
|
||||
function assertFileNotExist($file) {
|
||||
clearstatcache();
|
||||
$this->assertFalse(file_exists($file), 'Expected ' . $file . ' does not exist');
|
||||
}
|
||||
|
||||
|
@@ -254,9 +254,7 @@ a[href|title]
|
||||
|
||||
function test_addAttribute() {
|
||||
|
||||
$config = HTMLPurifier_Config::create(array(
|
||||
'HTML.DefinitionID' => 'HTMLPurifier_HTMLDefinitionTest->test_addAttribute'
|
||||
));
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$def = $config->getHTMLDefinition(true);
|
||||
$def->addAttribute('span', 'custom', 'Enum#attribute');
|
||||
|
||||
@@ -269,9 +267,7 @@ a[href|title]
|
||||
|
||||
function test_addAttribute_multiple() {
|
||||
|
||||
$config = HTMLPurifier_Config::create(array(
|
||||
'HTML.DefinitionID' => 'HTMLPurifier_HTMLDefinitionTest->test_addAttribute_multiple'
|
||||
));
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$def = $config->getHTMLDefinition(true);
|
||||
$def->addAttribute('span', 'custom', 'Enum#attribute');
|
||||
$def->addAttribute('span', 'foo', 'Text');
|
||||
@@ -285,9 +281,7 @@ a[href|title]
|
||||
|
||||
function test_addElement() {
|
||||
|
||||
$config = HTMLPurifier_Config::create(array(
|
||||
'HTML.DefinitionID' => 'HTMLPurifier_HTMLDefinitionTest->test_addElement'
|
||||
));
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$def = $config->getHTMLDefinition(true);
|
||||
$def->addElement('marquee', 'Inline', 'Inline', 'Common', array('width' => 'Length'));
|
||||
|
||||
@@ -299,8 +293,6 @@ a[href|title]
|
||||
}
|
||||
|
||||
function test_injector() {
|
||||
$this->config->set('HTML.DefinitionID', 'HTMLPurifier_HTMLDefinitionTest->test_injector');
|
||||
|
||||
generate_mock_once('HTMLPurifier_Injector');
|
||||
$injector = new HTMLPurifier_InjectorMock();
|
||||
$injector->name = 'MyInjector';
|
||||
@@ -317,8 +309,6 @@ a[href|title]
|
||||
}
|
||||
|
||||
function test_injectorMissingNeeded() {
|
||||
$this->config->set('HTML.DefinitionID', 'HTMLPurifier_HTMLDefinitionTest->test_injectorMissingNeeded');
|
||||
|
||||
generate_mock_once('HTMLPurifier_Injector');
|
||||
$injector = new HTMLPurifier_InjectorMock();
|
||||
$injector->name = 'MyInjector';
|
||||
@@ -333,8 +323,6 @@ a[href|title]
|
||||
}
|
||||
|
||||
function test_injectorIntegration() {
|
||||
$this->config->set('HTML.DefinitionID', 'HTMLPurifier_HTMLDefinitionTest->test_injectorIntegration');
|
||||
|
||||
$module = $this->config->getHTMLDefinition(true)->getAnonymousModule();
|
||||
$module->info_injector[] = 'Linkify';
|
||||
|
||||
@@ -345,8 +333,6 @@ a[href|title]
|
||||
}
|
||||
|
||||
function test_injectorIntegrationFail() {
|
||||
$this->config->set('HTML.DefinitionID', 'HTMLPurifier_HTMLDefinitionTest->test_injectorIntegrationFail');
|
||||
|
||||
$this->config->set('HTML.Allowed', 'p');
|
||||
|
||||
$module = $this->config->getHTMLDefinition(true)->getAnonymousModule();
|
||||
|
@@ -5,7 +5,6 @@ class HTMLPurifier_HTMLModule_SafeEmbedTest extends HTMLPurifier_HTMLModuleHarne
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
$this->config->set('HTML.DefinitionID', 'HTMLPurifier_HTMLModule_SafeEmbedTest');
|
||||
$def = $this->config->getHTMLDefinition(true);
|
||||
$def->manager->addModule('SafeEmbed');
|
||||
}
|
||||
|
@@ -80,9 +80,6 @@ alert(<b>bold</b>);
|
||||
}
|
||||
|
||||
function testRequiredAttributesTestNotPerformedOnEndTag() {
|
||||
$this->config->set('HTML.DefinitionID',
|
||||
'HTMLPurifier_Strategy_RemoveForeignElementsTest'.
|
||||
'->testRequiredAttributesTestNotPerformedOnEndTag');
|
||||
$def = $this->config->getHTMLDefinition(true);
|
||||
$def->addElement('f', 'Block', 'Optional: #PCDATA', false, array('req*' => 'Text'));
|
||||
$this->assertResult('<f req="text">Foo</f> Bar');
|
||||
|
Reference in New Issue
Block a user