removed leftovers from submodule uglifyjs, added credits file,

cleaned up CSS, changed template to output clean XHTML 5,
added unit tests for 60% of the code, found a few bugs by doing
that and fixed them
This commit is contained in:
Simon Rupf
2012-08-26 00:49:11 +02:00
parent f37303d858
commit 907538875b
32 changed files with 961 additions and 511 deletions

16
tst/README.md Normal file
View File

@@ -0,0 +1,16 @@
Running unit tests
==================
In order to run these tests, you will need to install the following packages
and its dependencies:
* phpunit
* php5-gd
* php5-sqlite
* php5-xdebug
Example for Debian and Ubuntu:
$ sudo aptitude install phpunit php5-mysql php5-xdebug
To run the tests, just change into this directory and run phpunit:
$ cd ZeroBin/tst
$ phpunit

77
tst/RainTPL.php Normal file
View File

@@ -0,0 +1,77 @@
<?php
class RainTPLTest extends PHPUnit_Framework_TestCase
{
private static $data = '{"iv":"EN39/wd5Nk8HAiSG2K5AsQ","salt":"QKN1DBXe5PI","ct":"8hA83xDdXjD7K2qfmw5NdA"}';
private static $error = 'foo bar';
private static $version = 'Version 1.2.3';
private $_content;
public function setUp()
{
/* Setup Routine */
$page = new RainTPL;
$page::configure(array('cache_dir' => 'tmp/'));
// We escape it here because ENT_NOQUOTES can't be used in RainTPL templates.
$page->assign('CIPHERDATA', htmlspecialchars(self::$data, ENT_NOQUOTES));
$page->assign('ERRORMESSAGE', self::$error);
$page->assign('OPENDISCUSSION', false);
$page->assign('VERSION', self::$version);
ob_start();
$page->draw('page');
$this->_content = ob_get_contents();
// run a second time from cache
$page->cache('page');
$page->draw('page');
ob_end_clean();
}
public function tearDown()
{
/* Tear Down Routine */
helper::rmdir(PATH . 'tmp');
}
public function testTemplateRendersCorrectly()
{
$this->assertTag(
array(
'id' => 'cipherdata',
'content' => htmlspecialchars(self::$data, ENT_NOQUOTES)
),
$this->_content,
'outputs data correctly'
);
$this->assertTag(
array(
'id' => 'errormessage',
'content' => self::$error
),
$this->_content,
'outputs error correctly'
);
$this->assertTag(
array(
'id' => 'opendiscussion',
'attributes' => array(
'disabled' => 'disabled'
),
),
$this->_content,
'disables discussions if configured'
);
// testing version number in JS address, since other instances may not be present in different templates
$this->assertTag(
array(
'tag' => 'script',
'attributes' => array(
'src' => 'js/zerobin.js?' . rawurlencode(self::$version)
),
),
$this->_content,
'outputs version correctly'
);
}
}

8
tst/auto.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
class autoTest extends PHPUnit_Framework_TestCase
{
public function testAutoloaderReturnsFalseWhenCallingNonExistingClass()
{
$this->assertFalse(auto::loader('foo2501bar42'), 'calling non existent class');
}
}

31
tst/bootstrap.php Normal file
View File

@@ -0,0 +1,31 @@
<?php
error_reporting( E_ALL | E_STRICT );
// change this, if your php files and data is outside of your webservers document root
define('PATH', '..' . DIRECTORY_SEPARATOR);
require PATH . 'lib/auto.php';
class helper
{
public static function rmdir($path)
{
$path .= DIRECTORY_SEPARATOR;
$dir = dir($path);
while(false !== ($file = $dir->read())) {
if($file != '.' && $file != '..') {
if(is_dir($path . $file)) {
self::rmdir($path . $file);
} elseif(is_file($path . $file)) {
if(!@unlink($path . $file)) {
throw new Exception('Error deleting file "' . $path . $file . '".');
}
}
}
}
$dir->close();
if(!@rmdir($path)) {
throw new Exception('Error deleting directory "' . $path . '".');
}
}
}

47
tst/filter.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
class filterTest extends PHPUnit_Framework_TestCase
{
public function testFilterStripsSlashesDeeply()
{
$this->assertEquals(
array("f'oo", "b'ar", array("fo'o", "b'ar")),
filter::stripslashes_deep(array("f\\'oo", "b\\'ar", array("fo\\'o", "b\\'ar")))
);
}
public function testFilterMakesSizesHumanlyReadable()
{
$this->assertEquals('1 B', filter::size_humanreadable(1));
$this->assertEquals('1 000 B', filter::size_humanreadable(1000));
$this->assertEquals('1.00 kiB', filter::size_humanreadable(1024));
$this->assertEquals('1.21 kiB', filter::size_humanreadable(1234));
$exponent = 1024;
$this->assertEquals('1 000.00 kiB', filter::size_humanreadable(1000 * $exponent));
$this->assertEquals('1.00 MiB', filter::size_humanreadable(1024 * $exponent));
$this->assertEquals('1.21 MiB', filter::size_humanreadable(1234 * $exponent));
$exponent *= 1024;
$this->assertEquals('1 000.00 MiB', filter::size_humanreadable(1000 * $exponent));
$this->assertEquals('1.00 GiB', filter::size_humanreadable(1024 * $exponent));
$this->assertEquals('1.21 GiB', filter::size_humanreadable(1234 * $exponent));
$exponent *= 1024;
$this->assertEquals('1 000.00 GiB', filter::size_humanreadable(1000 * $exponent));
$this->assertEquals('1.00 TiB', filter::size_humanreadable(1024 * $exponent));
$this->assertEquals('1.21 TiB', filter::size_humanreadable(1234 * $exponent));
$exponent *= 1024;
$this->assertEquals('1 000.00 TiB', filter::size_humanreadable(1000 * $exponent));
$this->assertEquals('1.00 PiB', filter::size_humanreadable(1024 * $exponent));
$this->assertEquals('1.21 PiB', filter::size_humanreadable(1234 * $exponent));
$exponent *= 1024;
$this->assertEquals('1 000.00 PiB', filter::size_humanreadable(1000 * $exponent));
$this->assertEquals('1.00 EiB', filter::size_humanreadable(1024 * $exponent));
$this->assertEquals('1.21 EiB', filter::size_humanreadable(1234 * $exponent));
$exponent *= 1024;
$this->assertEquals('1 000.00 EiB', filter::size_humanreadable(1000 * $exponent));
$this->assertEquals('1.00 ZiB', filter::size_humanreadable(1024 * $exponent));
$this->assertEquals('1.21 ZiB', filter::size_humanreadable(1234 * $exponent));
$exponent *= 1024;
$this->assertEquals('1 000.00 ZiB', filter::size_humanreadable(1000 * $exponent));
$this->assertEquals('1.00 YiB', filter::size_humanreadable(1024 * $exponent));
$this->assertEquals('1.21 YiB', filter::size_humanreadable(1234 * $exponent));
}
}

17
tst/phpunit.xml Normal file
View File

@@ -0,0 +1,17 @@
<phpunit bootstrap="bootstrap.php" colors="true">
<testsuite name="ZeroBin Test Suite">
<directory suffix=".php">./</directory>
</testsuite>
<filter>
<whitelist>
<directory suffix=".php">../lib</directory>
<exclude>
<file>../lib/zerobin/abstract.php</file>
</exclude>
</whitelist>
</filter>
<logging>
<log type="coverage-html" target="log/coverage-report" charset="UTF-8" yui="true" highlight="true" lowUpperBound="50" highLowerBound="80" />
<log type="testdox-html" target="log/testdox.html" />
</logging>
</phpunit>

14
tst/sjcl.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
class sjclTest extends PHPUnit_Framework_TestCase
{
public function testSjclValidatorValidatesCorrectly()
{
$this->assertTrue(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'valid sjcl');
$this->assertFalse(sjcl::isValid('{"iv":"$","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of iv');
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"$","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'invalid base64 encoding of salt');
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"Gx1vA2/gQ3U","ct":"$"}'), 'invalid base64 encoding of ct');
$this->assertFalse(sjcl::isValid('{"iv":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'iv to long');
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=","ct":"j7ImByuE5xCqD2YXm6aSyA"}'), 'salt to long');
$this->assertFalse(sjcl::isValid('{"iv":"83Ax/OdUav3SanDW9dcQPg","salt":"Gx1vA2/gQ3U","ct":"j7ImByuE5xCqD2YXm6aSyA","foo":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA="}'), 'invalid additional key');
}
}

30
tst/trafficlimiter.php Normal file
View File

@@ -0,0 +1,30 @@
<?php
class trafficlimiterTest extends PHPUnit_Framework_TestCase
{
private $_path;
public function setUp()
{
/* Setup Routine */
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'trafficlimit' . DIRECTORY_SEPARATOR;
trafficlimiter::setPath($this->_path);
}
public function tearDown()
{
/* Tear Down Routine */
helper::rmdir($this->_path);
}
public function testTrafficGetsLimited()
{
trafficlimiter::setLimit(4);
$this->assertTrue(trafficlimiter::canPass('127.0.0.1'), 'first request may pass');
sleep(2);
$this->assertFalse(trafficlimiter::canPass('127.0.0.1'), 'second request is to fast, may not pass');
sleep(3);
$this->assertTrue(trafficlimiter::canPass('127.0.0.1'), 'third request waited long enough and may pass');
$this->assertTrue(trafficlimiter::canPass('2001:1620:2057:dead:beef::cafe:babe'), 'fourth request has different ip and may pass');
$this->assertFalse(trafficlimiter::canPass('127.0.0.1'), 'fifth request is to fast, may not pass');
}
}

41
tst/vizhash16x16.php Normal file
View File

@@ -0,0 +1,41 @@
<?php
class vizhash16x16Test extends PHPUnit_Framework_TestCase
{
private $_dataDirCreated;
private $_file;
private $_path;
public function setUp()
{
/* Setup Routine */
$this->_path = PATH . 'data' . DIRECTORY_SEPARATOR;
$this->_dataDirCreated = !is_dir($this->_path);
if($this->_dataDirCreated) mkdir($this->_path);
$this->_file = $this->_path . 'vizhash.png';
}
public function tearDown()
{
/* Tear Down Routine */
if($this->_dataDirCreated) {
helper::rmdir($this->_path);
} else {
if(!@unlink($this->_file)) {
throw new Exception('Error deleting file "' . $this->_file . '".');
}
}
}
public function testVizhashGeneratesUniquePngsPerIp()
{
$vz = new vizhash16x16();
$pngdata = $vz->generate('127.0.0.1');
file_put_contents($this->_file, $pngdata);
$finfo = new finfo(FILEINFO_MIME_TYPE);
$this->assertEquals('image/png', $finfo->file($this->_file));
$this->assertNotEquals($pngdata, $vz->generate('2001:1620:2057:dead:beef::cafe:babe'));
$this->assertEquals($pngdata, $vz->generate('127.0.0.1'));
}
}

70
tst/zerobin/data.php Normal file
View File

@@ -0,0 +1,70 @@
<?php
class zerobin_dataTest extends PHPUnit_Framework_TestCase
{
private static $pasteid = '501f02e9eeb8bcec';
private static $paste = array(
'data' => '{"iv":"EN39/wd5Nk8HAiSG2K5AsQ","salt":"QKN1DBXe5PI","ct":"8hA83xDdXjD7K2qfmw5NdA"}',
'meta' => array(
'postdate' => 1344803344,
'expire_date' => 1344803644,
'opendiscussion' => true,
),
);
private static $commentid = 'c47efb4741195f42';
private static $comment = array(
'data' => '{"iv":"Pd4pOKWkmDTT9uPwVwd5Ag","salt":"ZIUhFTliVz4","ct":"6nOCU3peNDclDDpFtJEBKA"}',
'meta' => array(
'nickname' => '{"iv":"76MkAtOGC4oFogX/aSMxRA","salt":"ZIUhFTliVz4","ct":"b6Ae/U1xJdsX/+lATud4sQ"}',
'vizhash' => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGUlEQVQokWOsl5/94983CNKQMjnxaOePf98MeKwPfNjkLZ3AgARab6b9+PeNEVnDj3/ff/z7ZiHnzsDA8Pv7H2TVPJw8EAYLAwb48OaVgIgYKycLsrYv378wMDB8//qdCVMDRA9EKSsnCwRBxNsepaLboMFlyMDAICAi9uHNK24GITQ/MDAwoNhgIGMLtwGrzegaLjw5jMz9+vUdnN17uwDCQDhJgk0O07yvX9+teDX1x79v6DYIsIjgcgMaYGFgYOBg4kJx2JejkAiBxAw+PzAwMNz4dp6wDXDw4MdNNOl0rWYsNkD89OLXI/xmo9sgzatJjAYmBgYGDiauD3/ePP18nVgb4MF89+M5ZX6js293wUMpnr8KTQMAxsCJnJ30apMAAAAASUVORK5CYII=',
'postdate' => 1344803528,
),
);
private $_model;
private $_path;
public function setUp()
{
/* Setup Routine */
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'zerobin_data';
$this->_model = zerobin_data::getInstance(array('dir' => $this->_path));
}
public function tearDown()
{
/* Tear Down Routine */
helper::rmdir($this->_path);
}
public function testFileBasedDataStoreWorks()
{
// storing pastes
$this->assertFalse($this->_model->exists(self::$pasteid), 'paste does not yet exist');
$this->assertTrue($this->_model->create(self::$pasteid, self::$paste), 'store new paste');
$this->assertTrue($this->_model->exists(self::$pasteid), 'paste exists after storing it');
$this->assertFalse($this->_model->create(self::$pasteid, self::$paste), 'unable to store the same paste twice');
$this->assertEquals(json_decode(json_encode(self::$paste)), $this->_model->read(self::$pasteid));
// storing comments
$this->assertFalse($this->_model->existsComment(self::$pasteid, self::$pasteid, self::$commentid), 'comment does not yet exist');
$this->assertTrue($this->_model->createComment(self::$pasteid, self::$pasteid, self::$commentid, self::$comment) !== false, 'store comment');
$this->assertTrue($this->_model->existsComment(self::$pasteid, self::$pasteid, self::$commentid), 'comment exists after storing it');
$comment = json_decode(json_encode(self::$comment));
$comment->meta->commentid = self::$commentid;
$comment->meta->parentid = self::$pasteid;
$this->assertEquals(
array($comment->meta->postdate => $comment),
$this->_model->readComments(self::$pasteid)
);
// deleting pastes
$this->_model->delete(self::$pasteid);
$this->assertFalse($this->_model->exists(self::$pasteid), 'paste successfully deleted');
$this->assertFalse($this->_model->existsComment(self::$pasteid, self::$pasteid, self::$commentid), 'comment was deleted with paste');
$this->assertFalse($this->_model->read(self::$pasteid), 'paste can no longer be found');
}
}

68
tst/zerobin/db.php Normal file
View File

@@ -0,0 +1,68 @@
<?php
class zerobin_dbTest extends PHPUnit_Framework_TestCase
{
private static $pasteid = '501f02e9eeb8bcec';
private static $paste = array(
'data' => '{"iv":"EN39/wd5Nk8HAiSG2K5AsQ","salt":"QKN1DBXe5PI","ct":"8hA83xDdXjD7K2qfmw5NdA"}',
'meta' => array(
'postdate' => 1344803344,
'expire_date' => 1344803644,
'opendiscussion' => true,
),
);
private static $commentid = 'c47efb4741195f42';
private static $comment = array(
'data' => '{"iv":"Pd4pOKWkmDTT9uPwVwd5Ag","salt":"ZIUhFTliVz4","ct":"6nOCU3peNDclDDpFtJEBKA"}',
'meta' => array(
'nickname' => '{"iv":"76MkAtOGC4oFogX/aSMxRA","salt":"ZIUhFTliVz4","ct":"b6Ae/U1xJdsX/+lATud4sQ"}',
'vizhash' => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGUlEQVQokWOsl5/94983CNKQMjnxaOePf98MeKwPfNjkLZ3AgARab6b9+PeNEVnDj3/ff/z7ZiHnzsDA8Pv7H2TVPJw8EAYLAwb48OaVgIgYKycLsrYv378wMDB8//qdCVMDRA9EKSsnCwRBxNsepaLboMFlyMDAICAi9uHNK24GITQ/MDAwoNhgIGMLtwGrzegaLjw5jMz9+vUdnN17uwDCQDhJgk0O07yvX9+teDX1x79v6DYIsIjgcgMaYGFgYOBg4kJx2JejkAiBxAw+PzAwMNz4dp6wDXDw4MdNNOl0rWYsNkD89OLXI/xmo9sgzatJjAYmBgYGDiauD3/ePP18nVgb4MF89+M5ZX6js293wUMpnr8KTQMAxsCJnJ30apMAAAAASUVORK5CYII=',
'postdate' => 1344803528,
),
);
private $_model;
public function setUp()
{
/* Setup Routine */
$this->_model = zerobin_db::getInstance(
array(
'dsn' => 'sqlite::memory:',
'usr' => null,
'pwd' => null,
'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
)
);
}
public function testDatabaseBasedDataStoreWorks()
{
// storing pastes
$this->assertFalse($this->_model->exists(self::$pasteid), 'paste does not yet exist');
$this->assertTrue($this->_model->create(self::$pasteid, self::$paste), 'store new paste');
$this->assertTrue($this->_model->exists(self::$pasteid), 'paste exists after storing it');
$this->assertFalse($this->_model->create(self::$pasteid, self::$paste), 'unable to store the same paste twice');
$this->assertEquals(json_decode(json_encode(self::$paste)), $this->_model->read(self::$pasteid));
// storing comments
$this->assertFalse($this->_model->existsComment(self::$pasteid, self::$pasteid, self::$commentid), 'comment does not yet exist');
$this->assertTrue($this->_model->createComment(self::$pasteid, self::$pasteid, self::$commentid, self::$comment) !== false, 'store comment');
$this->assertTrue($this->_model->existsComment(self::$pasteid, self::$pasteid, self::$commentid), 'comment exists after storing it');
$comment = json_decode(json_encode(self::$comment));
$comment->meta->commentid = self::$commentid;
$comment->meta->parentid = self::$pasteid;
$this->assertEquals(
array($comment->meta->postdate => $comment),
$this->_model->readComments(self::$pasteid)
);
// deleting pastes
$this->_model->delete(self::$pasteid);
$this->assertFalse($this->_model->exists(self::$pasteid), 'paste successfully deleted');
$this->assertFalse($this->_model->existsComment(self::$pasteid, self::$pasteid, self::$commentid), 'comment was deleted with paste');
$this->assertFalse($this->_model->read(self::$pasteid), 'paste can no longer be found');
}
}