Begin Refactor

This commit is contained in:
color.diff=auto
2021-03-21 13:47:29 -06:00
parent 7622dc0d02
commit 018931d7ae
197 changed files with 47799 additions and 6 deletions

View File

@@ -0,0 +1,161 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\OODBBean as OODBBean;
use RedBeanPHP\Logger\RDefault\Debug as Debugger;
/**
* Debug
*
* Tests debugging functions and checks whether the output
* of the debugger displays the correct information.
*
* @file RedUNIT/Blackhole/Debug.php
* @desc Tests Debugger II.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Debug extends Blackhole
{
/**
* Given a query, a set of bindings and an expected outcome,
* this method tests the result of the debugger.
*
* @param string $query
* @param mixed $bindings
* @param string $expected
* @param integer $mode
* @param string $expected2
*
* @return void
*/
private function testDebug($query, $bindings = NULL, $expected, $mode = 1, $expected2 = NULL)
{
$debugger = new Debugger;
$debugger->setMode( $mode );
$debugger->setParamStringLength( 20 );
ob_start();
if (!is_null($bindings)) {
$debugger->log($query, $bindings);
} else {
$debugger->log($query);
}
$out = ob_get_contents();
ob_clean();
ob_end_flush();
$logs = $debugger->getLogs();
$log = reset($logs);
$log = str_replace( "\e[32m", '', $log );
$log = str_replace( "\e[39m", '', $log );
asrt($log, $expected);
if (!$mode) {
asrt($out, $expected2);
}
$debugger->clear();
}
/**
* Tests the bean dump function used to inspect
* the contents of a bean.
*
* @return void
*/
public function testDump()
{
$beans = R::dispense( 'bean', 2 );
$beans[0]->name = 'hello';
$beans[1]->name = 'world';
$array = R::dump($beans);
asrt( is_array( $array ), TRUE );
foreach( $array as $item ) {
asrt( is_string( $item ), TRUE );
}
$beans[1]->name = 'world, and a very long string that should be shortened';
$array = R::dump($beans);
asrt( is_array( $array ), TRUE );
asrt( strpos( $array[1], '...' ), 35 );
dmp( $beans );
pass();
//test wrong input
asrt( is_array( R::dump( NULL ) ), TRUE );
asrt( count( R::dump( NULL ) ), 0 );
asrt( is_array( R::dump( '' ) ), TRUE );
asrt( count( R::dump( '' ) ), 0 );
asrt( is_array( R::dump( 1 ) ), TRUE );
asrt( count( R::dump( 1 ) ), 0 );
asrt( is_array( R::dump( TRUE ) ), TRUE );
asrt( count( R::dump( FALSE ) ), 0 );
}
/**
* Tests debugging with parameters.
*
* @return void
*/
public function testDebugger2()
{
testpack( 'Test debugger with params.' );
$this->testDebug('SELECT * FROM table', NULL, 'SELECT * FROM table');
$this->testDebug('SELECT * FROM book WHERE title = ?', array('my book'), 'SELECT * FROM book WHERE title = \'my book\'');
$this->testDebug('title = ? OR title = ?', array('book1', 'book2'), 'title = \'book1\' OR title = \'book2\'');
$this->testDebug('title = ? OR price = ?', array('book1', 20), 'title = \'book1\' OR price = 20');
$this->testDebug('number IN (?,?)', array(8,900), 'number IN (8,900)');
$this->testDebug('?', array(20), '20');
$this->testDebug('?,?', array('test',20), '\'test\',20');
$this->testDebug('?', array( NULL ), 'NULL');
$this->testDebug('title = ?', array( NULL ), 'title = NULL');
$this->testDebug('?,?', array( NULL,NULL ), 'NULL,NULL');
$this->testDebug('title = ?', array('a very long title that should be shortened'), 'title = \'a very long title th... \'');
$this->testDebug('title = ? OR title = ?', array('a very long title that should be shortened', 'another long title that should be shortened'), 'title = \'a very long title th... \' OR title = \'another long title t... \'');
$this->testDebug('title = ? OR ?', array('a very long title that should be shortened', NULL), 'title = \'a very long title th... \' OR NULL');
$this->testDebug('?,?', array('hello'), '\'hello\',:slot1');
$this->testDebug('title = :first OR title = :second', array(':first'=>'book1', ':second'=>'book2'), 'title = \'book1\' OR title = \'book2\'');
$this->testDebug('title = :first OR price = :second', array(':first'=>'book1', ':second'=>20), 'title = \'book1\' OR price = 20');
$this->testDebug('number IN (:one,:two)', array(':one'=>8, ':two'=>900), 'number IN (8,900)');
$this->testDebug('number IN (:one,:two)', array(':one'=>8, ':two'=>900, ':three'=>999), 'number IN (8,900)');
$this->testDebug('number IN (:one,:two)', array(':three'=>999, ':one'=>8, ':two'=>900), 'number IN (8,900)');
$this->testDebug('number IN (:one,:two)', array(':one'=>8, ':three'=>999, ':two'=>900), 'number IN (8,900)');
$this->testDebug(':a', array(':a'=>20), '20');
$this->testDebug(':a,?', array(':a'=>20, 30), '20,30');
$this->testDebug(':a,?', array(30, ':a'=>20), '20,30');
$this->testDebug('?,?', array('test',20), '\'test\',20');
$this->testDebug('?', array( NULL ), 'NULL');
$this->testDebug('title = ?', array( NULL ), 'title = NULL');
$this->testDebug('?,?', array( NULL,NULL ), 'NULL,NULL');
$this->testDebug('title = ?', array('a very long title that should be shortened'), 'title = \'a very long title th... \'');
$this->testDebug('title = ? OR title = ?', array('a very long title that should be shortened', 'another long title that should be shortened'), 'title = \'a very long title th... \' OR title = \'another long title t... \'');
$this->testDebug('title = ? OR ?', array('a very long title that should be shortened', NULL), 'title = \'a very long title th... \' OR NULL');
$this->testDebug('?,?', array('hello'), '\'hello\',:slot1');
$this->testDebug('hello ?', 'world', 'hello ?');
$this->testDebug(':slot0 :slot1 :slot2 :slot3 :slot4 :slot5 :slot6 :slot7 :slot8 :slot9 :slot10', array(
'a','b','c','d','e','f','g','h','i','j','k'
),"'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k'");
$this->testDebug('? ? ? ? ? ? ? ? ? ? ?', array(
'a','b','c','d','e','f','g','h','i','j','k'
),"'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k'");
$this->testDebug(':a :aaa :ab', array(':a'=>1,':aaa'=>2,':ab'=>3),'1 2 3');
Debugger::setOverrideCLIOutput( TRUE );
$this->testDebug('SELECT * FROM table', NULL, 'SELECT * FROM table', 0, 'SELECT * FROM table<br />');
$this->testDebug('DROP TABLE myths', NULL, 'DROP TABLE myths', 0, '<b style="color:red">DROP TABLE myths</b><br />');
$this->testDebug('SELECT * FROM book WHERE title = ?', array('my book'), 'SELECT * FROM book WHERE title = <b style="color:green">\'my book\'</b>');
Debugger::setOverrideCLIOutput( FALSE );
}
/**
* Test facade fancyDebug function.
*
* @return void
*/
public function testDebug2InFacade()
{
R::fancyDebug( TRUE );
pass();
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\OODBBean as OODBBean;
/**
* Export
*
* Tests whether we can export beans to arrays and whether we can
* use the exportAll function to convert entire hierarchies into
* nested array structures.
*
* @file RedUNIT/Blackhole/Export.php
* @desc Tests basic bean exporting features.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Export extends Blackhole
{
/**
* ExportAll.
*
* @return void
*/
public function testExportAll()
{
testpack( 'Test exportAll' );
$redbean = R::getRedBean();
$bean = R::dispense('bean');
$bean->import( array( 'a' => 1, 'b' => 2 ) );
$bean->setMeta( 'justametaproperty', 'hellothere' );
$arr = $bean->export();
asrt( is_array( $arr ), TRUE );
asrt( isset( $arr["a"] ), TRUE );
asrt( isset( $arr["b"] ), TRUE );
asrt( $arr["a"], 1 );
asrt( $arr["b"], 2 );
asrt( isset( $arr["__info"] ), FALSE );
$arr = $bean->export( TRUE );
asrt( isset( $arr["__info"] ), TRUE );
asrt( $arr["a"], 1 );
asrt( $arr["b"], 2 );
$exportBean = $redbean->dispense( 'abean' );
$exportBean->setMeta( 'metaitem.bla', 1 );
$exportedBean = $exportBean->export( TRUE );
asrt( $exportedBean["__info"]["metaitem.bla"], 1 );
asrt( $exportedBean["__info"]["type"], "abean" );
// Can we determine whether a bean is empty?
testpack( 'test $bean->isEmpty() function' );
$bean = R::dispense( 'bean' );
asrt( $bean->isEmpty(), TRUE );
asrt( ( count( $bean ) > 0 ), TRUE );
$bean->property = 1;
asrt( $bean->isEmpty(), FALSE );
asrt( ( count( $bean ) > 0 ), TRUE );
$bean->property = 0;
asrt( $bean->isEmpty(), TRUE );
asrt( ( count( $bean ) > 0 ), TRUE );
$bean->property = FALSE;
asrt( $bean->isEmpty(), TRUE );
asrt( ( count( $bean ) > 0 ), TRUE );
$bean->property = NULL;
asrt( $bean->isEmpty(), TRUE );
asrt( ( count( $bean ) > 0 ), TRUE );
unset( $bean->property );
asrt( $bean->isEmpty(), TRUE );
asrt( ( count( $bean ) > 0 ), TRUE );
// Export bug I found
$bandmember = R::dispense( 'bandmember' );
$bandmember->name = 'Duke';
$instrument = R::dispense( 'instrument' );
$instrument->name = 'Piano';
$bandmember->ownInstrument[] = $instrument;
$a = R::exportAll( $bandmember );
pass();
asrt( isset( $a[0] ), TRUE );
asrt( (int) $a[0]['id'], 0 );
asrt( $a[0]['name'], 'Duke' );
asrt( $a[0]['ownInstrument'][0]['name'], 'Piano' );
R::nuke();
$v = R::dispense( 'village' );
$b = R::dispense( 'building' );
$v->name = 'a';
$b->name = 'b';
$v->ownBuilding[] = $b;
$id = R::store( $v );
$a = R::exportAll( $v );
asrt( $a[0]['name'], 'a' );
asrt( $a[0]['ownBuilding'][0]['name'], 'b' );
$v = R::load( 'village', $id );
$b2 = R::dispense( 'building' );
$b2->name = 'c';
$v->ownBuilding[] = $b2;
$a = R::exportAll( $v );
asrt( $a[0]['name'], 'a' );
asrt( $a[0]['ownBuilding'][0]['name'], 'b' );
asrt( count( $a[0]['ownBuilding'] ), 2 );
list( $r1, $r2 ) = R::dispense( 'army', 2 );
$r1->name = '1';
$r2->name = '2';
$v->sharedArmy[] = $r2;
$a = R::exportAll( $v );
asrt( count( $a[0]['sharedArmy'] ), 1 );
R::store( $v );
$v = R::load( 'village', $id );
$a = R::exportAll( $v );
asrt( count( $a[0]['sharedArmy'] ), 1 );
asrt( $a[0]['name'], 'a' );
asrt( $a[0]['ownBuilding'][0]['name'], 'b' );
asrt( count( $a[0]['ownBuilding'] ), 2 );
$v->sharedArmy[] = $r1;
$a = R::exportAll( $v );
asrt( count( $a[0]['sharedArmy'] ), 2 );
$v = R::load( 'village', $id );
$a = R::exportAll( $v );
asrt( count( $a[0]['sharedArmy'] ), 1 );
$v->sharedArmy[] = $r1;
R::store( $v );
$v = R::load( 'village', $id );
$a = R::exportAll( $v );
asrt( count( $a[0]['sharedArmy'] ), 2 );
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\OODBBean as OODBBean;
use RedBeanPHP\SimpleModel as SimpleModel;
/**
* Fusebox
*
* Tests whether we can convert a bean to a model and
* a model to a bean. This process is called boxing and
* unboxing.
*
* @file RedUNIT/Blackhole/Fusebox.php
* @desc Tests Boxing/Unboxing of beans.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Fusebox extends Blackhole
{
/**
* Test type hinting with boxed model
*
* @param Model_Soup $soup
*/
private function giveMeSoup( \Model_Soup $soup )
{
asrt( ( $soup instanceof \Model_Soup ), TRUE );
asrt( 'A bit too salty', $soup->taste() );
asrt( 'tomato', $soup->flavour );
}
/**
* Test unboxing
*
* @param OODBBean $bean
*/
private function giveMeBean( OODBBean $bean )
{
asrt( ( $bean instanceof OODBBean ), TRUE );
asrt( 'A bit too salty', $bean->taste() );
asrt( 'tomato', $bean->flavour );
}
/**
* Test boxing.
*
* @return void
*/
public function testBasicBox()
{
$soup = R::dispense( 'soup' );
$soup->flavour = 'tomato';
$this->giveMeSoup( $soup->box() );
$this->giveMeBean( $soup->box()->unbox() );
$this->giveMeBean( $soup );
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\QueryWriter as QueryWriter;
/**
* Glue
*
* RedBeanPHP does NOT parse entire queries and it does not
* ship with a query builder. However because RedBeanPHP
* facilitates mixing-in SQL snippets using methods like
* find(), via(), with(), withCondition() and so on...,
* it needs to be able to figure out how two query part strings
* can be connected to eachother. In particular parts beginning with or
* without 'WHERE', 'AND' and 'OR'. This test checks whether the
* QueryWriter has the ability to glue together query parts correctly.
* The gluer is part of the QueryWriter, however since this narrow
* slice of SQL syntax is so generic it's been implemented at Writer
* level and all drivers in RedBeanPHP inherit the generic implementation.
* At the moment of writing no additional glue methods had to be
* implemented.
*
* @file RedUNIT/Blackhole/Glue.php
* @desc Tests query gluer.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Glue extends Blackhole
{
/**
* Tests whether we can intelligently glue together SQL snippets.
*
* @return void
*/
public function testGlue()
{
$writer = R::getWriter();
//Can we add a condition without having to type 'WHERE' - usual suspects
asrt( $writer->glueSQLCondition( ' name = ? '), ' WHERE name = ? ' );
asrt( $writer->glueSQLCondition( ' value1 > ? OR value < ? '), ' WHERE value1 > ? OR value < ? ' );
//Does it recognize NON-WHERE conditions? - usual suspects
asrt( $writer->glueSQLCondition( ' ORDER BY name '), ' ORDER BY name ' );
asrt( $writer->glueSQLCondition( ' LIMIT 10 '), ' LIMIT 10 ' );
asrt( $writer->glueSQLCondition( ' OFFSET 20 '), ' OFFSET 20 ' );
//highly doubtful but who knows... - I think nobody will ever use this in a query snippet.
asrt( $writer->glueSQLCondition( ' GROUP BY grp '), ' GROUP BY grp ' );
asrt( $writer->glueSQLCondition( ' HAVING x = ? '), ' HAVING x = ? ' );
//can we replace WHERE with AND ?
asrt( $writer->glueSQLCondition( ' AND name = ? ', QueryWriter::C_GLUE_WHERE ), ' WHERE name = ? ' );
//can we glue with AND instead of WHERE ?
asrt( $writer->glueSQLCondition( ' value1 > ? OR value < ? ', QueryWriter::C_GLUE_AND ), ' AND value1 > ? OR value < ? ' );
//non-cases
asrt( $writer->glueSQLCondition( ' GROUP BY grp ', QueryWriter::C_GLUE_WHERE ), ' GROUP BY grp ' );
asrt( $writer->glueSQLCondition( ' GROUP BY grp ', QueryWriter::C_GLUE_AND ), ' GROUP BY grp ' );
}
}

View File

@@ -0,0 +1,283 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\OODBBean as OODBBean;
use RedBeanPHP\RedException as RedException;
/**
* Import
*
* RedBeanPHP offers some methods to import arrays into
* beans. For instance using the dispense() method. This
* test suite checks whether RedBeanPHP can correctly convert
* array structures to beans and also checks the expected effects
* on the taint flags. This test suite further tests the 'simple'
* single bean import() function, the inject() function (bean-to-bean) and
* array access (because this is somehow related).
*
* @file RedUNIT/Blackhole/Import.php
* @desc Tests basic bean importing features.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Import extends Blackhole
{
/**
* Test import without trimming.
*
* @return void
*/
public function testImportWithoutTrim()
{
$book = R::dispense( 'book' );
$book->import( array( ' title ' => 'my book' ), array( ' title ' ), TRUE );
asrt( $book[' title '], 'my book' );
}
/**
* Test multi array dispense import.
*
* @return void
*/
public function testMultiRecurImport()
{
$books = R::dispense( array(
array( '_type' => 'book', 'title' => 'book one' ),
array( '_type' => 'book', 'title' => 'book two' ),
) );
asrt( is_array( $books ), TRUE );
asrt( count( $books ), 2 );
$book = reset( $books );
asrt( ( $book instanceof OODBBean ), TRUE );
asrt( $book->title, 'book one' );
$book = next( $books );
asrt( ( $book instanceof OODBBean ), TRUE );
asrt( $book->title, 'book two' );
}
/**
* Test recursive imports (formely known as R::graph).
*
* @return void
*/
public function testRecursiveImport()
{
$book = R::dispense(
array(
'_type'=>'book',
'title'=>'The magic book',
'ownPageList' => array(
array(
'_type' => 'page',
'content' => 'magic potions',
),
array(
'_type' => 'page',
'content' => 'magic spells',
)
)
)
);
$id = R::store( $book );
$book = R::load( 'book', $id );
asrt( $book->title, 'The magic book' );
$pages = $book->with(' ORDER BY content ASC ')->ownPageList;
asrt( count($pages), 2 );
$page1 = array_shift( $pages );
asrt( $page1->content, 'magic potions' );
$page2 = array_shift( $pages );
asrt( $page2->content, 'magic spells' );
R::nuke();
$book = R::dispense(
array(
'_type'=>'book',
'title'=>'The magic book',
'author' => array(
'_type' => 'author',
'name' => 'Dr. Evil'
),
'coAuthor' => array(
'_type' => 'author',
'name' => 'Dr. Creepy'
),
'ownPageList' => array(
array(
'_type' => 'page',
'content' => 'magic potions',
'ownRecipe' => array(
'a' => array('_type'=>'recipe', 'name'=>'Invisibility Salad'),
'b' => array('_type'=>'recipe', 'name'=>'Soup of Madness'),
'c' => array('_type'=>'recipe', 'name'=>'Love cake'),
)
),
array(
'_type' => 'page',
'content' => 'magic spells',
)
),
'sharedCategory' => array(
array(
'_type' => 'category',
'label' => 'wizardry'
),
)
)
);
$id = R::store( $book );
$book = R::load( 'book', $id );
asrt( $book->title, 'The magic book' );
$pages = $book->with(' ORDER BY content ASC ')->ownPageList;
asrt( count($pages), 2 );
$page1 = array_shift( $pages );
asrt( $page1->content, 'magic potions' );
$page2 = array_shift( $pages );
asrt( $page2->content, 'magic spells' );
$recipes = $page1->with(' ORDER BY name ASC ')->ownRecipeList;
asrt( count( $recipes ), 3 );
$recipe1 = array_shift( $recipes );
asrt( $recipe1->name, 'Invisibility Salad' );
$recipe2 = array_shift( $recipes );
asrt( $recipe2->name, 'Love cake' );
$recipe3 = array_shift( $recipes );
asrt( $recipe3->name, 'Soup of Madness' );
$categories = $book->sharedCategoryList;
asrt( count($categories), 1 );
$category = reset( $categories );
asrt( $category->label, 'wizardry' );
asrt( $book->author->name, 'Dr. Evil' );
asrt( $book->fetchAs('author')->coAuthor->name, 'Dr. Creepy' );
try {
$list = R::dispense( array() );
pass();
asrt( is_array( $list ), TRUE );
asrt( count( $list ), 0 );
} catch ( RedException $ex ) {
pass();
}
try {
R::dispense( array( array() ) );
fail();
} catch ( RedException $ex ) {
pass();
}
try {
R::dispense( array( 'a' ) );
fail();
} catch ( RedException $ex ) {
pass();
}
try {
R::dispense( array( 'property' => 'value' ) );
fail();
} catch ( RedException $ex ) {
pass();
}
}
/**
* Test import from and tainted.
*
* @return void
*/
public function testImportFromAndTainted()
{
testpack( 'Test importFrom() and Tainted' );
$bean = R::dispense( 'bean' );
R::store( $bean );
$bean->name = 'abc';
asrt( $bean->getMeta( 'tainted' ), TRUE );
R::store( $bean );
asrt( $bean->getMeta( 'tainted' ), FALSE );
$copy = R::dispense( 'bean' );
R::store( $copy );
$copy = R::load( 'bean', $copy->id );
asrt( $copy->getMeta( 'tainted' ), FALSE );
$copy->import( array( 'name' => 'xyz' ) );
asrt( $copy->getMeta( 'tainted' ), TRUE );
$copy->setMeta( 'tainted', FALSE );
asrt( $copy->getMeta( 'tainted' ), FALSE );
$copy->importFrom( $bean );
asrt( $copy->getMeta( 'tainted' ), TRUE );
testpack( 'Test basic import() feature.' );
$bean = R::dispense('bean');
$bean->import( array( "a" => 1, "b" => 2 ) );
asrt( $bean->a, 1 );
asrt( $bean->b, 2 );
$bean->import( array( "a" => 3, "b" => 4 ), "a,b" );
asrt( $bean->a, 3 );
asrt( $bean->b, 4 );
$bean->import( array( "a" => 5, "b" => 6 ), " a , b " );
asrt( $bean->a, 5 );
asrt( $bean->b, 6 );
$bean->import( array( "a" => 1, "b" => 2 ) );
testpack( 'Test inject() feature.' );
$coffee = R::dispense( 'coffee' );
$coffee->id = 2;
$coffee->liquid = 'black';
$cup = R::dispense( 'cup' );
$cup->color = 'green';
// Pour coffee in cup
$cup->inject( $coffee );
// Do we still have our own property?
asrt( $cup->color, 'green' );
// Did we pour the liquid in the cup?
asrt( $cup->liquid, 'black' );
// Id should not be transferred
asrt( $cup->id, 0 );
}
/**
* Test import using array access functions
*
* @return void
*/
public function testArrayAccess()
{
$book = R::dispense( 'book' );
$book->isAwesome = TRUE;
asrt( isset( $book->isAwesome ), TRUE );
$book = R::dispense( 'book' );
$book['isAwesome'] = TRUE;
asrt( isset( $book->isAwesome ), TRUE );
$book = R::dispense( 'book' );
$book['xownPageList'] = R::dispense( 'page', 2 );
asrt( isset( $book->ownPage ), TRUE );
asrt( isset( $book->xownPage ), TRUE );
asrt( isset( $book->ownPageList ), TRUE );
asrt( isset( $book->xownPageList ), TRUE );
$book = R::dispense( 'book' );
$book['ownPageList'] = R::dispense( 'page', 2 );
asrt( isset( $book->ownPage ), TRUE );
asrt( isset( $book->xownPage ), TRUE );
asrt( isset( $book->ownPageList ), TRUE );
asrt( isset( $book->xownPageList ), TRUE );
$book = R::dispense( 'book' );
$book['xownPage'] = R::dispense( 'page', 2 );
asrt( isset( $book->ownPage ), TRUE );
asrt( isset( $book->xownPage ), TRUE );
asrt( isset( $book->ownPageList ), TRUE );
asrt( isset( $book->xownPageList ), TRUE );
$book = R::dispense( 'book' );
$book['ownPage'] = R::dispense( 'page', 2 );
asrt( isset( $book->ownPage ), TRUE );
asrt( isset( $book->xownPage ), TRUE );
asrt( isset( $book->ownPageList ), TRUE );
asrt( isset( $book->xownPageList ), TRUE );
$book = R::dispense( 'book' );
$book['sharedTag'] = R::dispense( 'tag', 2 );
asrt( isset( $book->sharedTag ), TRUE );
asrt( isset( $book->sharedTagList ), TRUE );
$book = R::dispense( 'book' );
$book['sharedTagList'] = R::dispense( 'tag', 2 );
asrt( isset( $book->sharedTag ), TRUE );
asrt( isset( $book->sharedTagList ), TRUE );
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\OODBBean as OODBBean;
/**
* Labels
*
* Labels are very simple beans, only having a title and an ID.
* The idea behind labels is that they are very easy to generate
* from a comma separated list and they can easily be converted
* to such a list. Labels can be used for simplistic relations in the
* database like tagging or enums.
*
* @file RedUNIT/Blackhole/Labels.php
* @desc Tests Facade Label functions.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Labels extends Blackhole
{
/**
* Test basic labels.
*
* @return void
*/
public function testLabels()
{
testpack( 'Test Labels' );
$meals = R::dispenseLabels( 'meal', array( 'meat', 'fish', 'vegetarian' ) );
asrt( is_array( $meals ), TRUE );
asrt( count( $meals ), 3 );
foreach ( $meals as $m ) {
asrt( ( $m instanceof OODBBean ), TRUE );
}
$listOfMeals = implode( ',', R::gatherLabels( $meals ) );
asrt( $listOfMeals, 'fish,meat,vegetarian' );
}
}

View File

@@ -0,0 +1,123 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\OODBBean as OODBBean;
/**
* Meta
*
* Beans can have meta data. Meta data will not be stored
* in the database and cannot be loaded from the database
* (except for using special meta masks - this feature is available
* in 4.3.2+). This test suite tests whether we can set and get
* meta data from beans and verifies meta data does not end up
* in the database.
*
* @file RedUNIT/Blackhole/Meta.php
* @desc Tests meta data features on OODBBean class.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Meta extends Blackhole
{
/**
* Test meta data methods.
*
* @return void
*/
public function testMetaData()
{
testpack( 'Test meta data' );
$bean = new OODBBean;
$bean->setMeta( "this.is.a.custom.metaproperty", "yes" );
asrt( $bean->getMeta( "this.is.a.custom.metaproperty" ), "yes" );
asrt( $bean->getMeta( "nonexistant" ), NULL );
asrt( $bean->getMeta( "nonexistant", "abc" ), "abc" );
asrt( $bean->getMeta( "nonexistant.nested" ), NULL );
asrt( $bean->getMeta( "nonexistant,nested", "abc" ), "abc" );
$bean->setMeta( "test.two", "second" );
asrt( $bean->getMeta( "test.two" ), "second" );
$bean->setMeta( "another.little.property", "yes" );
asrt( $bean->getMeta( "another.little.property" ), "yes" );
asrt( $bean->getMeta( "test.two" ), "second" );
// Copy Metadata
$bean = new OODBBean;
$bean->setMeta( "meta.meta", "123" );
$bean2 = new OODBBean;
asrt( $bean2->getMeta( "meta.meta" ), NULL );
$bean2->copyMetaFrom( $bean );
asrt( $bean2->getMeta( "meta.meta" ), "123" );
}
/**
* Meta properties should not be saved.
*
* @return void
*/
public function testMetaPersist()
{
$bean = R::dispense( 'bean' );
$bean->property = 'test';
$bean->setMeta( 'meta', 'hello' );
R::store( $bean );
asrt( $bean->getMeta( 'meta' ), 'hello' );
$bean = $bean->fresh();
asrt( $bean->getMeta( 'meta' ), NULL );
}
/**
* You cant access meta data using the array accessors.
*
* @return void
*/
public function testNoArrayMetaAccess()
{
$bean = R::dispense( 'bean' );
$bean->setMeta( 'greet', 'hello' );
asrt( isset( $bean['greet'] ), FALSE );
asrt( isset( $bean['__info']['greet'] ), FALSE );
asrt( isset( $bean['__info'] ), FALSE );
asrt( isset( $bean['meta'] ), FALSE );
asrt( count( $bean ), 1 );
}
/**
* Test meta masks.
*
* @return void
*/
public function testMetaMask()
{
$rows = array(
array('id'=>1, 'name'=>'a', '__meta_rows'=>2, '__meta_columns'=>4),
array('id'=>2, 'name'=>'b', '__meta_rows'=>2, '__meta_columns'=>4)
);
$books = R::convertToBeans( 'book', $rows, '__meta' );
$book = reset($books);
$data = $book->getMeta('data.bundle');
asrt( $data['__meta_rows'], 2 );
asrt( $data['__meta_columns'], 4 );
$books = R::convertToBeans( 'book', $rows, array( '__meta_rows', '__meta_columns' ) );
$book = reset($books);
$data = $book->getMeta('data.bundle');
asrt( $data['__meta_rows'], 2 );
asrt( $data['__meta_columns'], 4 );
$books = R::convertToBeans( 'book', $rows, array( '__meta_rows' ) );
$book = reset($books);
$data = $book->getMeta('data.bundle');
asrt( $data['__meta_rows'], 2 );
asrt( isset($data['__meta_columns']), FALSE );
$books = R::convertToBeans( 'book', $rows, array( '__meta_rows', TRUE ) );
$book = reset($books);
$data = $book->getMeta('data.bundle');
asrt( isset($data['__meta_rows']), FALSE );
asrt( isset($data['__meta_columns']), FALSE );
}
}

View File

@@ -0,0 +1,624 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\OODBBean as OODBBean;
use RedBeanPHP\Driver\RPDO as RPDO;
use RedBeanPHP\Logger\RDefault as RDefault;
use RedBeanPHP\RedException as RedException;
use RedBeanPHP\BeanHelper\SimpleFacadeBeanHelper as SimpleFacadeBeanHelper;
use RedBeanPHP\QueryWriter;
use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter;
use RedBeanPHP\QueryWriter\MySQL as MySQLQueryWriter;
use RedBeanPHP\QueryWriter\PostgreSQL as PostgresQueryWriter;
/**
* Misc
*
* This test suite contains tests for a various functionalities
* and scenarios. For more details please consult the document
* section attached to each individual test method listed here.
*
* @file RedUNIT/Blackhole/Misc.php
* @desc Tests various features that do not rely on a database connection.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Misc extends Blackhole
{
/*
* What drivers should be loaded for this test pack?
*/
public function getTargetDrivers()
{
return array( 'sqlite' );
}
/**
* Test whether we get the correct exception if we try to
* add a database we don't have a compatible QueryWriter for.
*
* @return void
*/
public function testUnsupportedDatabaseWriter()
{
$exception = NULL;
try {
R::addDatabase( 'x', 'blackhole:host=localhost;dbname=db', 'username', 'password' );
} catch( \Exception $e ) {
$exception = $e;
}
asrt( ( $exception instanceof RedException ), TRUE );
asrt( $exception->getMessage(), 'Unsupported database (blackhole).' );
$rpdo = new \TestRPO( new \MockPDO );
asrt( @$rpdo->testCap( 'utf8mb4' ), FALSE );
}
/**
* Misc tests.
* 'Tests' almost impossible lines to test.
* Not sure if very useful.
*
* @return void
*/
public function testMisc()
{
$null = R::getDatabaseAdapter()->getDatabase()->stringifyFetches( TRUE );
asrt( NULL, $null );
R::getDatabaseAdapter()->getDatabase()->stringifyFetches( FALSE );
}
/**
* Test whether we can toggle enforcement of the RedBeanPHP
* naming policy.
*
* @return void
*/
public function testEnforceNamingPolicy()
{
\RedBeanPHP\Util\DispenseHelper::setEnforceNamingPolicy( FALSE );
R::dispense('a_b');
pass();
\RedBeanPHP\Util\DispenseHelper::setEnforceNamingPolicy( TRUE );
try {
R::dispense('a_b');
fail();
} catch( \Exception $e ) {
pass();
}
}
/**
* Test R::csv()
*
* @return void
*/
public function testCSV()
{
\RedBeanPHP\Util\QuickExport::operation( 'test', TRUE, TRUE );
R::nuke();
$city = R::dispense('city');
$city->name = 'city1';
$city->region = 'region1';
$city->population = '200k';
R::store($city);
$qe = new \RedBeanPHP\Util\QuickExport( R::getToolBox() );
$out = $qe->csv( 'SELECT `name`, population FROM city WHERE region = :region ',
array( ':region' => 'region1' ),
array( 'city', 'population' ),
'/tmp/cities.csv'
);
$out = preg_replace( '/\W/', '', $out );
asrt( 'PragmapublicExpires0CacheControlmustrevalidatepostcheck0precheck0CacheControlprivateContentTypetextcsvContentDispositionattachmentfilenamecitiescsvContentTransferEncodingbinarycitypopulationcity1200k', $out );
}
/**
* Test whether sqlStateIn can detect lock timeouts.
*
* @return void
*/
public function testLockTimeoutDetection()
{
$queryWriter = new MySQLQueryWriter( R::getDatabaseAdapter() );
asrt($queryWriter->sqlStateIn('HY000', array(QueryWriter::C_SQLSTATE_LOCK_TIMEOUT), array(0,'1205')), TRUE);
$queryWriter = new PostgresQueryWriter( R::getDatabaseAdapter() );
asrt($queryWriter->sqlStateIn('55P03', array(QueryWriter::C_SQLSTATE_LOCK_TIMEOUT), array(0,'')), TRUE);
}
/**
* Tests setOption
*
* @return void
*/
public function testSetOptionFalse()
{
$false = R::getDatabaseAdapter()->setOption( 'unknown', 1 );
asrt( $false, FALSE );
}
/**
* Test whether we can use the JSONSerializable interface and
* whether old-style JSON is still the same (backwards compatibility).
*
* @return void
*/
public function testJSONSerialize()
{
$hotel = R::dispense( 'hotel' );
$hotel->name = 'Overlook';
$room = R::dispense( 'room' );
$room->number = 237;
$hotel->ownRoomList[] = $room;
$shine = (string) $hotel;
asrt( $shine, '{"id":0,"name":"Overlook"}' ); //basic JSON
$shine = json_encode( $hotel->jsonSerialize() ); //As of PHP 5.4 json_encode() will call jsonSerializable
asrt( $shine, '{"id":0,"name":"Overlook","ownRoom":[{"id":0,"number":237}]}' ); //should get full JSON
}
/**
* Tests max parameter binding.
*
* @return void
*/
public function testIntegerBindingMax()
{
if ( defined( 'HHVM_VERSION' ) ) return; //not for hhvm...
$driver = new RPDO( 'test-sqlite-53', 'user', 'pass' );
$max = $driver->getIntegerBindingMax();
asrt( $max, 2147483647 );
$driver = new RPDO( 'cubrid', 'user', 'pass' );
$max = $driver->getIntegerBindingMax();
asrt( $max, 2147483647 );
$driver = new RPDO( 'other', 'user', 'pass' );
$max = $driver->getIntegerBindingMax();
asrt( $max, PHP_INT_MAX );
}
/**
* Should not be able to pass invalid mode (must be 0 or 1).
*
*/
public function testInvalidDebugModeException()
{
try {
R::debug( TRUE, 6 );
fail();
} catch ( RedException $e ) {
pass();
}
R::debug( FALSE );
}
/**
* Adding a database twice no longer allowed, causes confusion
* and possible damage.
*/
public function testAddingTwice()
{
testpack( 'Test adding DB twice.' );
try {
R::addDatabase( 'sqlite', '' );
fail();
} catch ( RedException $ex ) {
pass();
}
}
/**
* Tests whether getID never produces a notice.
*
* @return void
*/
public function testGetIDShouldNeverPrintNotice()
{
set_error_handler(function($err, $errStr){
die('>>>>FAIL :'.$err.' '.$errStr);
});
$bean = new OODBBean;
$bean->getID();
restore_error_handler();
pass();
}
/**
* Tests setProperty.
*
* @return void
*/
public function testSetProperty()
{
$bean = R::dispense( 'bean' );
$bean->item = 2;
$bean->ownBean = R::dispense( 'bean', 2 );
R::store( $bean );
$bean = $bean->fresh();
$bean->ownBean;
$bean->setProperty( 'ownBean', array(), FALSE, FALSE );
asrt( count( $bean->ownBean ), 0 );
asrt( count( $bean->getMeta( 'sys.shadow.ownBean' ) ), 2 );
asrt( $bean->isTainted(), TRUE );
$bean->setProperty( 'ownBean', array(), TRUE, FALSE );
asrt( count( $bean->ownBean ), 0 );
asrt( count( $bean->getMeta( 'sys.shadow.ownBean' ) ), 0 );
asrt( $bean->isTainted(), TRUE );
$bean = $bean->fresh();
$bean->setProperty( 'ownBean', array(), TRUE, FALSE );
asrt( count( $bean->ownBean ), 0 );
asrt( count( $bean->getMeta( 'sys.shadow.ownBean' ) ), 0 );
asrt( $bean->isTainted(), FALSE );
$bean = $bean->fresh();
$bean->setProperty( 'ownBean', array(), TRUE, TRUE );
asrt( count( $bean->ownBean ), 0 );
asrt( count( $bean->getMeta( 'sys.shadow.ownBean' ) ), 0 );
asrt( $bean->isTainted(), TRUE );
}
/**
* Tests beansToArray().
*
* @return void
*/
public function testBeansToArray()
{
testpack('Test R::beansToArray method');
$bean1 = R::dispense( 'bean' );
$bean1->name = 'hello';
$bean2 = R::dispense( 'bean' );
$bean2->name = 'world';
$beans = array( $bean1, $bean2 );
$array = R::beansToArray( $beans );
asrt( $array[0]['name'], 'hello' );
asrt( $array[1]['name'], 'world' );
}
/**
* Test debugging with custom logger.
*
* @return void
*/
public function testDebugCustomLogger()
{
testpack( 'Test debug mode with custom logger' );
$pdoDriver = new RPDO( R::getDatabaseAdapter()->getDatabase()->getPDO() );
$customLogger = new \CustomLogger;
$pdoDriver->setDebugMode( TRUE, $customLogger );
$pdoDriver->Execute( 'SELECT 123' );
asrt( count( $customLogger->getLogMessage() ), 1 );
$pdoDriver->setDebugMode( TRUE, NULL );
asrt( ( $pdoDriver->getLogger() instanceof RDefault ), TRUE );
testpack( 'Test bean->getProperties method' );
$bean = R::dispense( 'bean' );
$bean->property = 'hello';
$props = $bean->getProperties();
asrt( isset( $props['property'] ), TRUE );
asrt( $props['property'], 'hello' );
}
/**
* Test Facade transactions.
*
* @return void
*
* @throws\Exception
*/
public function testTransactionInFacade()
{
testpack( 'Test transaction in facade' );
$bean = R::dispense( 'bean' );
$bean->name = 'a';
R::store( $bean );
R::trash( $bean );
R::freeze( TRUE );
$bean = R::dispense( 'bean' );
$bean->name = 'a';
R::store( $bean );
asrt( R::count( 'bean' ), 1 );
R::trash( $bean );
asrt( R::count( 'bean' ), 0 );
$bean = R::dispense( 'bean' );
$bean->name = 'a';
$id = R::transaction( function() use( &$bean ) {
return R::transaction( function() use( &$bean ) {
return R::store( $bean );
} );
} );
asrt( (int) $id, (int) $bean->id );
R::trash( $bean );
$bean = R::dispense( 'bean' );
$bean->name = 'a';
$id = R::transaction( function() use( &$bean ) {
return R::store( $bean );
} );
asrt( (int) $id, (int) $bean->id );
R::trash( $bean );
$bean = R::dispense( 'bean' );
$bean->name = 'a';
try {
R::transaction( function () use ( $bean ) {
R::store( $bean );
R::transaction( function () {
throw new\Exception();
} );
} );
} catch (\Exception $e ) {
pass();
}
asrt( R::count( 'bean' ), 0 );
$bean = R::dispense( 'bean' );
$bean->name = 'a';
try {
R::transaction( function () use ( $bean ) {
R::transaction( function () use ( $bean ) {
R::store( $bean );
throw new\Exception();
} );
} );
} catch (\Exception $e ) {
pass();
}
asrt( R::count( 'bean' ), 0 );
$bean = R::dispense( 'bean' );
$bean->name = 'a';
try {
R::transaction( function () use ( $bean ) {
R::transaction( function () use ( $bean ) {
R::store( $bean );
} );
} );
} catch (\Exception $e ) {
pass();
}
asrt( R::count( 'bean' ), 1 );
R::freeze( FALSE );
try {
R::transaction( 'nope' );
fail();
} catch (\Exception $e ) {
pass();
}
testpack( 'Test Camelcase 2 underscore' );
$names = array(
'oneACLRoute' => 'one_acl_route',
'ALLUPPERCASE' => 'alluppercase',
'clientServerArchitecture' => 'client_server_architecture',
'camelCase' => 'camel_case',
'peer2peer' => 'peer2peer',
'fromUs4You' => 'from_us4_you',
'lowercase' => 'lowercase',
'a1A2b' => 'a1a2b',
);
$bean = R::dispense( 'bean' );
foreach ( $names as $name => $becomes ) {
$bean->$name = 1;
asrt( isset( $bean->$becomes ), TRUE );
}
testpack( 'Misc Tests' );
R::debug( 1 );
flush();
ob_start();
R::exec( 'SELECT 123' );
$out = ob_get_contents();
ob_end_clean();
flush();
pass();
asrt( ( strpos( $out, 'SELECT 123' ) !== FALSE ), TRUE );
R::debug( 0 );
flush();
ob_start();
R::exec( 'SELECT 123' );
$out = ob_get_contents();
ob_end_clean();
flush();
pass();
asrt( $out, '' );
R::debug( 0 );
pass();
testpack( 'test to string override' );
$band = R::dispense( 'band' );
$str = strval( $band );
asrt( $str, 'bigband' );
testpack( 'test whether we can use isset/set in model' );
$band->setProperty( 'property1', 123 );
asrt( $band->property1, 123 );
asrt( $band->checkProperty( 'property1' ), TRUE );
asrt( $band->checkProperty( 'property2' ), FALSE );
$band = new \Model_Band;
$bean = R::dispense( 'band' );
$bean->property3 = 123;
$band->loadBean( $bean );
$bean->property4 = 345;
$band->setProperty( 'property1', 123 );
asrt( $band->property1, 123 );
asrt( $band->checkProperty( 'property1' ), TRUE );
asrt( $band->checkProperty( 'property2' ), FALSE );
asrt( $band->property3, 123 );
asrt( $band->property4, 345 );
testpack( 'Can we pass a\PDO object to Setup?' );
$pdo = new \PDO( 'sqlite:test.db' );
R::addDatabase( 'pdo', $pdo );
R::selectDatabase( 'pdo' );
R::getCell('SELECT 123;');
testpack( 'Test array interface of beans' );
$bean = R::dispense( 'bean' );
$bean->hello = 'hi';
$bean->world = 'planet';
asrt( $bean['hello'], 'hi' );
asrt( isset( $bean['hello'] ), TRUE );
asrt( isset( $bean['bye'] ), FALSE );
$bean['world'] = 'sphere';
asrt( $bean->world, 'sphere' );
foreach ( $bean as $key => $el ) {
if ( $el == 'sphere' || $el == 'hi' || $el == 0 ) {
pass();
} else {
fail();
}
if ( $key == 'hello' || $key == 'world' || $key == 'id' ) {
pass();
} else {
fail();
}
}
asrt( count( $bean ), 3 );
unset( $bean['hello'] );
asrt( count( $bean ), 2 );
asrt( count( R::dispense( 'countable' ) ), 1 );
// Otherwise untestable...
$bean->setBeanHelper( new SimpleFacadeBeanHelper() );
R::getRedBean()->setBeanHelper( new SimpleFacadeBeanHelper() );
pass();
// Test whether properties like owner and shareditem are still possible
testpack( 'Test Bean Interface for Lists' );
$bean = R::dispense( 'bean' );
// Must not be list, because first char after own is lowercase
asrt( is_array( $bean->owner ), FALSE );
// Must not be list, because first char after shared is lowercase
asrt( is_array( $bean->shareditem ), FALSE );
asrt( is_array( $bean->own ), FALSE );
asrt( is_array( $bean->shared ), FALSE );
asrt( is_array( $bean->own_item ), FALSE );
asrt( is_array( $bean->shared_item ), FALSE );
asrt( is_array( $bean->{'own item'} ), FALSE );
asrt( is_array( $bean->{'shared Item'} ), FALSE );
}
public function testConv2Beans()
{
$row1 = array('id' => 1, 'title'=>'test');
$row2 = array('id' => 2, 'title'=>'test2');
$beans = R::convertToBeans('page', array($row1, $row2));
asrt(count($beans), 2);
asrt($beans[2]->title, 'test2');
}
/**
* Test the most important invalid bean combinations.
*
* @return void
*/
public function testInvalidType()
{
$invalid = array(
'book_page', //no link beans
'a_b_c', //no prefix
'a b', //no space
'bean@', //no invalid symbols
'bean#', //no invalid symbols
'bean$', //sometimes used in DB, not allowed
'__bean',//no prefixes
'.bean', //no object notation
'bean-item', //no dash
'beanOther'); //no camelcase (uppercase because of file system issues)
foreach( $invalid as $j ) {
try {
R::dispense( $j );
fail();
} catch( RedException $e ) {
pass();
}
}
}
/**
* Test whether batch still works if no IDs have been passed.
*
* @return void
*/
public function testBatch0()
{
$zero = R::batch( 'page', array() );
asrt( is_array( $zero ), TRUE );
asrt( count( $zero ), 0 );
$zero = R::batch( 'page', FALSE );
asrt( is_array( $zero ), TRUE );
asrt( count( $zero ), 0 );
$zero = R::batch( 'page', NULL);
asrt( is_array( $zero ), TRUE );
asrt( count( $zero ), 0 );
}
/**
* Test whether connection failure does not reveal
* credentials.
*
* @return void
*/
public function testConnect()
{
$driver = new RPDO( 'dsn:invalid', 'usr', 'psst' );
try {
$driver->connect();
fail();
}
catch( \PDOException $e ) {
asrt( strpos( $e->getMessage(), 'invalid' ), FALSE );
asrt( strpos( $e->getMessage(), 'usr' ), FALSE );
asrt( strpos( $e->getMessage(), 'psst' ), FALSE );
}
}
/**
* Test whether we can create an instant database using
* R::setup().
*
* Probably only works on *NIX systems.
*
* @return void
*/
public function testSetup()
{
$tmpDir = sys_get_temp_dir();
R::setup();
}
/**
* Test camelCase to snake_case conversions.
*
* @return void
*/
public function testCamel2Snake()
{
asrt( AQueryWriter::camelsSnake('bookPage'), 'book_page' );
asrt( AQueryWriter::camelsSnake('FTP'), 'ftp' );
asrt( AQueryWriter::camelsSnake('ACLRules'), 'acl_rules' );
asrt( AQueryWriter::camelsSnake('SSHConnectionProxy'), 'ssh_connection_proxy' );
asrt( AQueryWriter::camelsSnake('proxyServerFacade'), 'proxy_server_facade' );
asrt( AQueryWriter::camelsSnake('proxySSHClient'), 'proxy_ssh_client' );
asrt( AQueryWriter::camelsSnake('objectACL2Factory'), 'object_acl2_factory' );
asrt( AQueryWriter::camelsSnake('bookItems4Page'), 'book_items4_page' );
asrt( AQueryWriter::camelsSnake('book☀Items4Page'), 'book☀_items4_page' );
}
/**
* Test that init SQL is being executed upon setting PDO.
*
* @return void
*/
public function testRunInitCodeOnSetPDO()
{
$pdo = R::getToolBox()->getDatabaseAdapter()->getDatabase()->getPDO();
$rpdo = new \RedBeanPHP\Driver\RPDO( $pdo );
$rpdo->setEnableLogging(true);
$logger = new \RedBeanPHP\Logger\RDefault\Debug;
$logger->setMode( \RedBeanPHP\Logger\RDefault::C_LOGGER_ARRAY );
$rpdo->setLogger( $logger );
$rpdo->setInitQuery('SELECT 123');
$rpdo->setPDO( $pdo );
$found = $logger->grep('SELECT 123');
asrt(count($found), 1);
asrt($found[0], 'SELECT 123');
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\Facade as Facade;
use RedBeanPHP\RedException as RedException;
/**
* Plugins
*
* This test suite tests whether we can define dynamic
* plugins using the ext() method on the facade.
*
* @file RedUNIT/Blackhole/Plugins.php
* @desc Tests extending R facade dynamically.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Plugins extends Blackhole
{
/**
* Test if we can dynamically extend the R-facade.
*
* @return void
*/
public function testDynamicPlugins()
{
testpack('Test dynamic plugins');
R::ext( 'makeTea', function() {
return 'sorry cant do that!';
});
asrt( R::makeTea(), 'sorry cant do that!' );
//with parameters
R::ext( 'multiply', function( $a, $b ) {
return $a * $b;
});
asrt( R::multiply( 3, 4 ), 12 );
//can we call R inside?
R::ext( 'singVersion', function() {
return R::getVersion() . ' lalala !';
} );
asrt( R::singVersion(), ( R::getVersion().' lalala !' ) );
//should also work with Facade
asrt( Facade::singVersion(), ( R::getVersion().' lalala !' ) );
//test error handling
try {
R::ext( '---', function() {} );
fail();
} catch ( RedException $e ) {
asrt( $e->getMessage(), 'Plugin name may only contain alphanumeric characters and underscores and cannot start with a number.' );
}
try {
R::__callStatic( '---', function() {} );
fail();
} catch ( RedException $e ) {
asrt( $e->getMessage(), 'Plugin name may only contain alphanumeric characters and underscores and cannot start with a number.' );
}
try {
R::invalidMethod();
fail();
} catch ( RedException $e ) {
asrt( $e->getMessage(), 'Plugin \'invalidMethod\' does not exist, add this plugin using: R::ext(\'invalidMethod\')' );
}
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Base as Base;
use RedBeanPHP\Facade as R;
use RedBeanPHP\OODBBean as OODBBean;
/**
* Stab tests for VMs without CUBRID database
*
* Tests CUBRID driver but without DB.
* For full tests see CUBRID test folder.
*
* @file RedUNIT/Base/Stub.php
* @desc Tests CUBRID without actual DB (mock adapter)
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Stub extends Base
{
/**
* Test CUBRID.
*
* @return void
*/
public function testCUBRID()
{
$mockdapter = new \Mockdapter();
$writer = new \DiagnosticCUBRIDWriter( $mockdapter );
pass();
$type = 'bean';
$targetType = 'other';
$property = 'property';
$targetProperty = 'other';
$value = 'value';
$properties = array( 'property','other' );
$table = 'bean';
$column = 'field';
$list = array();
$typedescription = ' STRING ';
$state = '';
$field = 'field';
$dbStructure = 'test';
$name = 'name';
$mockdapter->answerGetCol = array();
$writer->callMethod( 'buildFK', $type, $targetType, $property, $targetProperty, $isDep = FALSE );
pass();
$mockdapter->errorExec = new \RedBeanPHP\RedException\SQL('Test Exception');
$writer->callMethod( 'buildFK', $type, $targetType, $property, $targetProperty, $isDep = FALSE );
pass();
$mockdapter->errorExec = NULL;
$mockdapter->answerGetSQL = array(
array(
'CREATE TABLE' => 'CONSTRAINT [key] FOREIGN KEY ([bean]) REFERENCES [bean] ON DELETE CASCADE ON UPDATE RESTRICT'
)
);
$writer->addFK( $type, $targetType, $property, $targetProperty, $isDependent = FALSE );
pass();
$writer->callMethod( 'getKeyMapForType', 'bean' );
pass();
$writer->getTypeForID();
pass();
$writer->getTables();
pass();
$writer->createTable( $table );
pass();
$mockdapter->answerGetSQL = array(array('Field'=>'title','Type'=>'STRING'));
$writer->getColumns( $table );
pass();
asrt( $writer->scanType( 123, $flagSpecial = FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_INTEGER );
asrt( $writer->scanType( 12.3, $flagSpecial = FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_DOUBLE );
asrt( $writer->scanType( '0001', $flagSpecial = FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_STRING );
asrt( $writer->scanType( '1001', $flagSpecial = FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_INTEGER );
asrt( $writer->scanType( NULL, $flagSpecial = FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_INTEGER );
asrt( $writer->scanType( '2019-01-01', $flagSpecial = FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_STRING );
asrt( $writer->scanType( '2019-01-01 10:00:00', $flagSpecial = FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_STRING );
asrt( $writer->scanType( '2019-01-01', $flagSpecial = TRUE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_SPECIAL_DATE );
asrt( $writer->scanType( '2019-01-01 10:00:00', $flagSpecial = TRUE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_SPECIAL_DATETIME );
pass();
$writer->code( $typedescription, $includeSpecials = FALSE );
$writer->code( $typedescription, $includeSpecials = TRUE );
asrt( $writer->code( 'INTEGER', FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_INTEGER );
asrt( $writer->code( 'DOUBLE', FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_DOUBLE );
asrt( $writer->code( 'STRING', FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_STRING );
asrt( $writer->code( 'DATE', FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_SPECIFIED );
asrt( $writer->code( 'DATETIME', FALSE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_SPECIFIED );
asrt( $writer->code( 'INTEGER', TRUE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_INTEGER );
asrt( $writer->code( 'DOUBLE', TRUE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_DOUBLE );
asrt( $writer->code( 'STRING', TRUE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_STRING );
asrt( $writer->code( 'DATE', TRUE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_SPECIAL_DATE );
asrt( $writer->code( 'DATETIME', TRUE ), \RedBeanPHP\QueryWriter\CUBRID::C_DATATYPE_SPECIAL_DATETIME );
pass();
$writer->addColumn( $type, $column, $field );
pass();
$writer->addUniqueConstraint( $type, $properties );
$mockdapter->errorExec = new \RedBeanPHP\RedException\SQL('Test Exception');
$writer->addUniqueConstraint( $type, $properties );
pass();
asrt( $writer->sqlStateIn( 'HY000', array() ), FALSE );
asrt( $writer->sqlStateIn( 'HY000', array(\RedBeanPHP\QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION) ), TRUE );
pass();
$writer->addIndex( $type, $name, $column );
pass();
$mockdapter->errorExec = NULL;
$writer->addIndex( $type, $name, $column );
pass();
$writer->wipeAll();
pass();
$mockdapter->answerGetCol = array( 'table1' );
$mockdapter->answerGetSQL = array(
array(
'CREATE TABLE' => 'CONSTRAINT [key] FOREIGN KEY ([bean]) REFERENCES [bean] ON DELETE CASCADE ON UPDATE RESTRICT'
)
);
$writer->wipeAll();
pass();
$writer->esc( $dbStructure, $noQuotes = FALSE );
pass();
}
/**
* Test base implementation of getKeyMapForType().
*
* @return void
*/
public function testKeyMap()
{
$proxyWriter = new \ProxyWriter;
$empty = $proxyWriter->callMethod( $proxyWriter, 'getKeyMapForType', 'bean' );
asrt( is_array( $empty ), TRUE );
asrt( count( $empty ), 0 );
}
/**
* Test whether autoresolve() function for BC exists.
*
* @return void
*/
public function testSetAutoResolve()
{
R::setAutoResolve( TRUE );
pass();
}
}

View File

@@ -0,0 +1,131 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
/**
* Tainted
*
* This test suite tests whether beans are marked as tainted
* under the correct circumstances.
*
* @file RedUNIT/Blackhole/Tainted.php
* @desc Tests tainted flag for OODBBean objects.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Tainted extends Blackhole
{
/**
* Test whether we can detect a change using hasChanged().
*
* @return void
*/
public function testHasChangedList()
{
R::nuke();
$book = R::dispense( 'book' );
$page = R::dispense( 'page' );
asrt( $book->hasListChanged( 'ownPage' ), FALSE );
$book->ownPage[] = $page;
asrt( $book->hasListChanged( 'ownPage' ), TRUE );
R::store( $book );
$book = $book->fresh();
asrt( $book->hasListChanged( 'ownPage' ), FALSE );
$page = R::dispense( 'page' );
$book->ownPageList[] = $page;
asrt( $book->hasListChanged( 'ownPage' ), TRUE );
R::store( $book );
$book = $book->fresh();
asrt( $book->hasListChanged( 'ownPage' ), FALSE );
asrt( count( $book->ownPageList ), 2 );
array_pop( $book->ownPageList );
asrt( count( $book->ownPageList ), 1 );
asrt( $book->hasListChanged( 'ownPage' ), TRUE );
array_pop( $book->ownPageList );
asrt( count( $book->ownPageList ), 0 );
asrt( $book->hasListChanged( 'ownPage' ), TRUE );
$book = $book->fresh();
asrt( $book->hasListChanged( 'ownPage' ), FALSE );
asrt( count( $book->ownPageList ), 2 );
$otherPage = R::dispense( 'page' );
array_pop( $book->ownPageList );
$book->ownPageList[] = $otherPage;
asrt( count( $book->ownPageList ), 2 );
asrt( $book->hasListChanged( 'ownPage' ), TRUE );
$book = $book->fresh();
$firstPage = reset( $book->ownPageList );
$firstPage->content = 'abc';
asrt( $book->hasListChanged( 'ownPage' ), FALSE );
$book = $book->fresh();
asrt( $book->hasListChanged( 'ownPage' ), FALSE );
$lastPage = end( $book->ownPageList );
$lastPage->ownText[] = R::dispense( 'text' );
asrt( $book->hasListChanged( 'ownPage' ), FALSE );
}
/**
* Tests whether we can clear the history of a bean.
*
* @return void
*/
public function testClearHist()
{
R::nuke();
$book = R::dispense( 'book' );
asrt( $book->hasChanged( 'title' ), FALSE );
$book->title = 'book';
asrt( $book->hasChanged( 'title' ), TRUE );
R::store( $book );
asrt( $book->hasChanged( 'title' ), TRUE );
$book->clearHistory();
asrt( $book->hasChanged( 'title' ), FALSE );
}
/**
* Test tainted.
*
* @return void
*/
public function testTainted()
{
testpack( 'Original Tainted Tests' );
$redbean = R::getRedBean();
$spoon = $redbean->dispense( "spoon" );
asrt( $spoon->getMeta( "tainted" ), TRUE );
$spoon->dirty = "yes";
asrt( $spoon->getMeta( "tainted" ), TRUE );
testpack( 'Tainted List test' );
$note = R::dispense( 'note' );
$note->text = 'abc';
$note->ownNote[] = R::dispense( 'note' )->setAttr( 'text', 'def' );
$id = R::store( $note );
$note = R::load( 'note', $id );
asrt( $note->isTainted(), FALSE );
// Shouldn't affect tainted
$note->text;
asrt( $note->isTainted(), FALSE );
$note->ownNote;
asrt( $note->isTainted(), TRUE );
testpack( 'Tainted Test Old Value' );
$text = $note->old( 'text' );
asrt( $text, 'abc' );
asrt( $note->hasChanged( 'text' ), FALSE );
$note->text = 'xxx';
asrt( $note->hasChanged( 'text' ), TRUE );
$text = $note->old( 'text' );
asrt( $text, 'abc' );
testpack( 'Tainted Non-exist' );
asrt( $note->hasChanged( 'text2' ), FALSE );
testpack( 'Misc Tainted Tests' );
$bean = R::dispense( 'bean' );
$bean->hasChanged( 'prop' );
$bean->old( 'prop' );
}
}

View File

@@ -0,0 +1,164 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\ToolBox as TB;
use RedBeanPHP\QueryWriter as QueryWriter;
use RedBeanPHP\Adapter as Adapter;
use RedBeanPHP\OODB as OODB;
use RedBeanPHP\BeanHelper as BeanHelper;
use RedBeanPHP\BeanHelper\SimpleFacadeBeanHelper as SimpleFacadeBeanHelper;
use RedBeanPHP\Repository as Repository;
use RedBeanPHP\Repository\Fluid as FluidRepo;
use RedBeanPHP\Repository\Frozen as FrozenRepo;
use RedBeanPHP\RedException as RedException;
/**
* Toolbox
*
* The Toolbox acts as a kind of micro service locator.
* The toolbox is passed around by RedBeanPHP core objects
* to share services. It contains an adapter, a query writer
* and the RedBeanPHP Object Database object (OODB).
* This test suite focuses on the toolbox.
*
* @file RedUNIT/Blackhole/Toolbox.php
* @desc Toolbox tests.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Toolbox extends Blackhole {
/**
* Tests the hasDatabase() method.
*
* @return void
*/
public function testDatabaseCheck()
{
R::addDatabase( 'key1', 'mysql:dsn1', 'user1', 'password1', TRUE );
asrt( R::hasDatabase( 'key1' ), TRUE );
asrt( R::hasDatabase( 'key2' ), FALSE );
}
/**
* Github issue #458, selectDatabase causes PHP notice undefined index
* if database key not found.
*
* @return void
*/
public function testInvalidDB()
{
try {
R::selectDatabase( 'idontexist' );
fail();
} catch ( RedException $exception ) {
pass();
}
}
/**
* Test whether we can obtain a toolbox properly.
*
* @return void
*/
public function testCanWeObtainToolbox()
{
$toolbox = R::getToolBox();
asrt( ( $toolbox instanceof TB), TRUE );
$extractedToolbox = R::getExtractedToolbox();
asrt( is_array( $extractedToolbox ), TRUE );
asrt( count( $extractedToolbox ), 4 );
asrt( ( $extractedToolbox[0] instanceof OODB ), TRUE );
asrt( ( $extractedToolbox[1] instanceof Adapter ), TRUE );
asrt( ( $extractedToolbox[2] instanceof QueryWriter ), TRUE );
asrt( ( $extractedToolbox[3] instanceof TB ), TRUE );
$beanHelper = new SimpleFacadeBeanHelper;
$toolbox2 = $beanHelper->getToolbox();
asrt( ( $toolbox2 instanceof TB), TRUE );
asrt( $toolbox, $toolbox2 );
$extractedToolbox = $beanHelper->getExtractedToolbox();
asrt( is_array( $extractedToolbox ), TRUE );
asrt( count( $extractedToolbox ), 4 );
asrt( ( $extractedToolbox[0] instanceof OODB ), TRUE );
asrt( ( $extractedToolbox[1] instanceof Adapter ), TRUE );
asrt( ( $extractedToolbox[2] instanceof QueryWriter ), TRUE );
asrt( ( $extractedToolbox[3] instanceof TB ), TRUE );
}
/**
* Does the toolbox contain the necessary tools ?
*
* @return void
*/
public function testDoesToolboxContainTheTools()
{
$toolbox = R::getToolBox();
asrt( ( $toolbox->getDatabaseAdapter() instanceof Adapter ), TRUE );
asrt( ( $toolbox->getRedBean() instanceof OODB ), TRUE );
asrt( ( $toolbox->getWriter() instanceof QueryWriter ), TRUE );
}
/**
* Tests whether freeze() switches the repository object
* as it is supposed to do.
*
* @return void
*/
public function testRepoSwitching()
{
asrt( class_exists( 'RedBeanPHP\Repository' ), TRUE );
asrt( class_exists( 'RedBeanPHP\Repository\Fluid' ), TRUE );
asrt( class_exists( 'RedBeanPHP\Repository\Frozen' ), TRUE );
R::freeze( FALSE );
$redbean = R::getRedBean();
$repo = $redbean->getCurrentRepository();
asrt( is_object( $repo ), TRUE );
asrt( ( $repo instanceof Repository ), TRUE );
asrt( ( $repo instanceof FluidRepo ), TRUE );
R::freeze( TRUE );
$fluid = $repo;
$repo = $redbean->getCurrentRepository();
asrt( is_object( $repo ), TRUE );
asrt( ( $repo instanceof Repository ), TRUE );
asrt( ( $repo instanceof FrozenRepo ), TRUE );
$frozen = $repo;
R::freeze( FALSE );
$redbean = R::getRedBean();
$repo = $redbean->getCurrentRepository();
asrt( is_object( $repo ), TRUE );
asrt( ( $repo instanceof Repository ), TRUE );
asrt( ( $repo instanceof FluidRepo ), TRUE );
asrt( $repo, $fluid );
R::freeze( TRUE );
$fluid = $repo;
$repo = $redbean->getCurrentRepository();
asrt( is_object( $repo ), TRUE );
asrt( ( $repo instanceof Repository ), TRUE );
asrt( ( $repo instanceof FrozenRepo ), TRUE );
asrt( $repo, $frozen );
R::freeze( FALSE );
}
/**
* Can we add and remove toolboxes using
* neat accessors?
*
* @return void
*/
public function testAddRemoveToolBox()
{
$t1 = R::getToolBox();
R::addToolBoxWithKey( 't1', $t1 );
asrt( ( R::getToolBoxByKey('t2') instanceof Toolbox), FALSE );
asrt( ( R::getToolBoxByKey('t1') instanceof Toolbox), FALSE );
asrt( R::removeToolBoxByKey('t1'), TRUE );
asrt( R::removeToolBoxByKey('t2'), FALSE );
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace RedUNIT\Blackhole;
use RedUNIT\Blackhole as Blackhole;
use RedBeanPHP\Facade as R;
use RedBeanPHP\OODBBean;
/**
* Version
*
* This test suite tests whether we can properly
* obtain the version string. It also tests the availability
* of 'well known' entities like R, EID() and SimpleModel.
*
* @file RedUNIT/Blackhole/Version.php
* @desc Tests identification features.
* @author Gabor de Mooij and the RedBeanPHP Community
* @license New BSD/GPLv2
*
* (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
* This source file is subject to the New BSD/GPLv2 License that is bundled
* with this source code in the file license.txt.
*/
class Version extends Blackhole
{
/**
* Returns all features as a single string of
* comma separated values. For testing only.
*
* @return string
*/
private function getFeatureFlags()
{
$features = array();
$old = OODBBean::useFluidCount( TRUE );
OODBBean::useFluidCount( $old );
$features[] = intval( $old );
$old = R::noNuke( TRUE );
R::noNuke( $old );
$features[] = intval( $old );
$features[] = 0;
$old = R::setAllowHybridMode( TRUE );
R::setAllowHybridMode( $old );
$features[] = intval( $old );
$old = R::useISNULLConditions( TRUE );
R::useISNULLConditions( $old );
$features[] = intval( $old );
$features = implode( ',', $features );
return $features;
}
/**
* Test version info.
*
* @return void
*/
public function testVersion()
{
$version = R::getVersion();
asrt( is_string( $version ), TRUE );
}
/**
* Test whether basic tools are available for use.
*
* @return void
*/
public function testTools()
{
asrt( class_exists( '\\RedBean_SimpleModel' ), TRUE );
asrt( class_exists( '\\R' ), TRUE );
asrt( function_exists( 'EID' ), TRUE );
}
/**
* Test whether every label returns the correct set of
* feature flags.
*
* @return void
*/
public function testFeature()
{
R::useFeatureSet('original');
asrt( $this->getFeatureFlags(), '1,0,0,0,0' );
R::useFeatureSet('5.3');
asrt( $this->getFeatureFlags(), '1,0,0,0,0' );
R::useFeatureSet('novice/5.3');
asrt( $this->getFeatureFlags(), '1,1,0,0,0' );
R::useFeatureSet('5.4');
asrt( $this->getFeatureFlags(), '0,0,0,1,1' );
R::useFeatureSet('latest');
asrt( $this->getFeatureFlags(), '0,0,0,1,1' );
R::useFeatureSet('novice/5.4');
asrt( $this->getFeatureFlags(), '0,1,0,0,1' );
R::useFeatureSet('5.5');
asrt( $this->getFeatureFlags(), '0,0,0,1,1' );
R::useFeatureSet('novice/5.5');
asrt( $this->getFeatureFlags(), '0,1,0,0,1' );
R::useFeatureSet('novice/latest');
asrt( $this->getFeatureFlags(), '0,1,0,0,1' );
R::useFeatureSet('original');
asrt( $this->getFeatureFlags(), '1,0,0,0,0' );
}
/**
* Test whether an invalid feature set label will
* cause an exception.
*
* @return void
*/
public function testInvalidFeatureLabel()
{
try {
R::useFeatureSet('Invalid');
fail();
} catch( \Exception $e ) {
pass();
}
}
}