created initial unit tests for main zerobin class

This commit is contained in:
El RIDO 2015-08-27 23:30:35 +02:00
parent f775da3931
commit d57d6cf44b
6 changed files with 156 additions and 36 deletions

View file

@ -93,7 +93,8 @@ class zerobin
// create new paste or comment // create new paste or comment
if (!empty($_POST['data'])) if (!empty($_POST['data']))
{ {
$this->_create($_POST['data']); echo $this->_create($_POST['data']);
return;
} }
// delete an existing paste // delete an existing paste
elseif (!empty($_GET['deletetoken']) && !empty($_GET['pasteid'])) elseif (!empty($_GET['deletetoken']) && !empty($_GET['pasteid']))
@ -182,7 +183,7 @@ class zerobin
trafficlimiter::setPath($this->_conf['traffic']['dir']); trafficlimiter::setPath($this->_conf['traffic']['dir']);
if ( if (
!trafficlimiter::canPass($_SERVER['REMOTE_ADDR']) !trafficlimiter::canPass($_SERVER['REMOTE_ADDR'])
) $this->_return_message( ) return $this->_return_message(
1, 1,
'Please wait ' . 'Please wait ' .
$this->_conf['traffic']['limit'] . $this->_conf['traffic']['limit'] .
@ -193,7 +194,7 @@ class zerobin
$sizelimit = (int) $this->_getMainConfig('sizelimit', 2097152); $sizelimit = (int) $this->_getMainConfig('sizelimit', 2097152);
if ( if (
strlen($data) > $sizelimit strlen($data) > $sizelimit
) $this->_return_message( ) return $this->_return_message(
1, 1,
'Paste is limited to ' . 'Paste is limited to ' .
filter::size_humanreadable($sizelimit) . filter::size_humanreadable($sizelimit) .
@ -201,7 +202,7 @@ class zerobin
); );
// Make sure format is correct. // Make sure format is correct.
if (!sjcl::isValid($data)) $this->_return_message(1, 'Invalid data.'); if (!sjcl::isValid($data)) return $this->_return_message(1, 'Invalid data.');
// Read additional meta-information. // Read additional meta-information.
$meta=array(); $meta=array();
@ -268,7 +269,7 @@ class zerobin
} }
} }
if ($error) $this->_return_message(1, 'Invalid data.'); if ($error) return $this->_return_message(1, 'Invalid data.');
// Add post date to meta. // Add post date to meta.
$meta['postdate'] = time(); $meta['postdate'] = time();
@ -293,7 +294,7 @@ class zerobin
if ( if (
!filter::is_valid_paste_id($pasteid) || !filter::is_valid_paste_id($pasteid) ||
!filter::is_valid_paste_id($parentid) !filter::is_valid_paste_id($parentid)
) $this->_return_message(1, 'Invalid data.'); ) return $this->_return_message(1, 'Invalid data.');
// Comments do not expire (it's the paste that expires) // Comments do not expire (it's the paste that expires)
unset($storage['expire_date']); unset($storage['expire_date']);
@ -302,26 +303,26 @@ class zerobin
// Make sure paste exists. // Make sure paste exists.
if ( if (
!$this->_model()->exists($pasteid) !$this->_model()->exists($pasteid)
) $this->_return_message(1, 'Invalid data.'); ) return $this->_return_message(1, 'Invalid data.');
// Make sure the discussion is opened in this paste. // Make sure the discussion is opened in this paste.
$paste = $this->_model()->read($pasteid); $paste = $this->_model()->read($pasteid);
if ( if (
!$paste->meta->opendiscussion !$paste->meta->opendiscussion
) $this->_return_message(1, 'Invalid data.'); ) return $this->_return_message(1, 'Invalid data.');
// Check for improbable collision. // Check for improbable collision.
if ( if (
$this->_model()->existsComment($pasteid, $parentid, $dataid) $this->_model()->existsComment($pasteid, $parentid, $dataid)
) $this->_return_message(1, 'You are unlucky. Try again.'); ) return $this->_return_message(1, 'You are unlucky. Try again.');
// New comment // New comment
if ( if (
$this->_model()->createComment($pasteid, $parentid, $dataid, $storage) === false $this->_model()->createComment($pasteid, $parentid, $dataid, $storage) === false
) $this->_return_message(1, 'Error saving comment. Sorry.'); ) return $this->_return_message(1, 'Error saving comment. Sorry.');
// 0 = no error // 0 = no error
$this->_return_message(0, $dataid); return $this->_return_message(0, $dataid);
} }
// The user posts a standard paste. // The user posts a standard paste.
else else
@ -329,12 +330,12 @@ class zerobin
// Check for improbable collision. // Check for improbable collision.
if ( if (
$this->_model()->exists($dataid) $this->_model()->exists($dataid)
) $this->_return_message(1, 'You are unlucky. Try again.'); ) return $this->_return_message(1, 'You are unlucky. Try again.');
// New paste // New paste
if ( if (
$this->_model()->create($dataid, $storage) === false $this->_model()->create($dataid, $storage) === false
) $this->_return_message(1, 'Error saving paste. Sorry.'); ) return $this->_return_message(1, 'Error saving paste. Sorry.');
// Generate the "delete" token. // Generate the "delete" token.
// The token is the hmac of the pasteid signed with the server salt. // The token is the hmac of the pasteid signed with the server salt.
@ -342,10 +343,10 @@ class zerobin
$deletetoken = hash_hmac('sha1', $dataid, serversalt::get()); $deletetoken = hash_hmac('sha1', $dataid, serversalt::get());
// 0 = no error // 0 = no error
$this->_return_message(0, $dataid, array('deletetoken' => $deletetoken)); return $this->_return_message(0, $dataid, array('deletetoken' => $deletetoken));
} }
$this->_return_message(1, 'Server error.'); return $this->_return_message(1, 'Server error.');
} }
/** /**
@ -532,6 +533,6 @@ class zerobin
$result['id'] = $message; $result['id'] = $message;
} }
$result += $other; $result += $other;
exit(json_encode($result)); return json_encode($result);
} }
} }

View file

@ -2,7 +2,7 @@
error_reporting( E_ALL | E_STRICT ); error_reporting( E_ALL | E_STRICT );
// change this, if your php files and data is outside of your webservers document root // change this, if your php files and data is outside of your webservers document root
define('PATH', '..' . DIRECTORY_SEPARATOR); if (!defined('PATH')) define('PATH', '..' . DIRECTORY_SEPARATOR);
require PATH . 'lib/auto.php'; require PATH . 'lib/auto.php';

View file

@ -1,17 +0,0 @@
<?php
define('MCRYPT_DEV_URANDOM', 1);
function mcrypt_create_iv($int, $flag)
{
$randomSalt = '';
for($i = 0; $i < 16; ++$i) {
$randomSalt .= base_convert(mt_rand(), 10, 16);
}
// hex2bin requires an even length, pad if necessary
if (strlen($randomSalt) % 2)
{
$randomSalt = '0' . $randomSalt;
}
return hex2bin($randomSalt);
}

View file

@ -1,7 +1,6 @@
<phpunit bootstrap="bootstrap.php" colors="true"> <phpunit bootstrap="bootstrap.php" colors="true">
<testsuite name="ZeroBin Test Suite"> <testsuite name="ZeroBin Test Suite">
<directory suffix=".php">./</directory> <directory suffix=".php">./</directory>
<exclude>mcrypt_mock.php</exclude>
</testsuite> </testsuite>
<filter> <filter>
<whitelist> <whitelist>

View file

@ -35,7 +35,22 @@ class serversaltTest extends PHPUnit_Framework_TestCase
// generating new salt // generating new salt
serversalt::setPath($this->_path); serversalt::setPath($this->_path);
$salt = serversalt::get(); $salt = serversalt::get();
require 'mcrypt_mock.php';
// mcrypt mock
if (!defined('MCRYPT_DEV_URANDOM')) define('MCRYPT_DEV_URANDOM', 1);
function mcrypt_create_iv($int, $flag)
{
$randomSalt = '';
for($i = 0; $i < 256; ++$i) {
$randomSalt .= base_convert(mt_rand(), 10, 16);
}
// hex2bin requires an even length, pad if necessary
if (strlen($randomSalt) % 2)
{
$randomSalt = '0' . $randomSalt;
}
return hex2bin($randomSalt);
}
$this->assertNotEquals($salt, serversalt::generate()); $this->assertNotEquals($salt, serversalt::generate());
// try setting a different path and resetting it // try setting a different path and resetting it

122
tst/zerobin.php Normal file
View file

@ -0,0 +1,122 @@
<?php
class zerobinTest extends PHPUnit_Framework_TestCase
{
private static $pasteid = '501f02e9eeb8bcec';
private static $paste = array(
'data' => '{"iv":"EN39/wd5Nk8HAiSG2K5AsQ","v":1,"iter":1000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"QKN1DBXe5PI","ct":"8hA83xDdXjD7K2qfmw5NdA"}',
'meta' => array(
'postdate' => 1344803344,
'opendiscussion' => true,
),
);
private $_model;
public function setUp()
{
/* Setup Routine */
$this->_model = zerobin_data::getInstance(array('dir' => PATH . 'data'));
serversalt::setPath(PATH . 'data');
$this->reset();
}
public function tearDown()
{
/* Tear Down Routine */
}
public function reset()
{
$_POST = array();
$_GET = array();
$_SERVER = array();
if ($this->_model->exists(self::$pasteid))
$this->_model->delete(self::$pasteid);
}
/**
* @runInSeparateProcess
*/
public function testView()
{
$this->reset();
ob_start();
new zerobin;
$content = ob_get_contents();
$this->assertTag(
array(
'tag' => 'title',
'content' => 'ZeroBin'
),
$content,
'outputs title correctly'
);
}
/**
* @runInSeparateProcess
*/
public function testCreate()
{
$this->reset();
$_POST = self::$paste;
$_SERVER['REMOTE_ADDR'] = '::1';
ob_start();
new zerobin;
$content = ob_get_contents();
$response = json_decode($content, true);
$this->assertEquals($response['status'], 0, 'outputs status');
$this->assertEquals(
$response['deletetoken'],
hash_hmac('sha1', $response['id'], serversalt::get()),
'outputs valid delete token'
);
$this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
}
/**
* @runInSeparateProcess
*/
public function testRead()
{
$this->reset();
$this->_model->create(self::$pasteid, self::$paste);
$_SERVER['QUERY_STRING'] = self::$pasteid;
ob_start();
new zerobin;
$content = ob_get_contents();
$this->assertTag(
array(
'id' => 'cipherdata',
'content' => htmlspecialchars(json_encode(self::$paste), ENT_NOQUOTES)
),
$content,
'outputs data correctly'
);
}
/**
* @runInSeparateProcess
*/
public function testDelete()
{
$this->reset();
$this->_model->create(self::$pasteid, self::$paste);
$this->assertTrue($this->_model->exists(self::$pasteid), 'paste exists before deleting data');
$_GET['pasteid'] = self::$pasteid;
$_GET['deletetoken'] = hash_hmac('sha1', self::$pasteid, serversalt::get());
ob_start();
new zerobin;
$content = ob_get_contents();
$this->assertTag(
array(
'id' => 'status',
'content' => 'Paste was properly deleted'
),
$content,
'outputs deleted status correctly'
);
$this->assertFalse($this->_model->exists(self::$pasteid), 'paste successfully deleted');
}
}