1
0
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:
Edward Z. Yang
2010-12-30 23:51:53 +00:00
parent 6dcc37cb55
commit f3d050c517
11 changed files with 375 additions and 91 deletions

View File

@@ -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();

View File

@@ -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

View File

@@ -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');
}

View File

@@ -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();

View File

@@ -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');
}

View File

@@ -80,9 +80,6 @@ alert(&lt;b&gt;bold&lt;/b&gt;);
}
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');