/** * Test types. * Test how RedBeanPHP OODB and OODBBean handle type and type casts. * * Rules: * * 1. before storing a bean all types are preserved except booleans (they are converted to STRINGS '0' or '1') * 2. after store-reload all bean property values are STRINGS or NULL * (or ARRAYS but that's only from a user perspective because these are lazy loaded) * 3. the ID returned by store() is an INTEGER (if possible; on 32 bit systems overflowing values will be cast to STRINGS!) * * After loading: * ALL VALUES EXCEPT NULL -> STRING * NULL -> NULL * * @note Why not simply return bean->id in store()? Because not every driver returns the same type: * databases without insert_id support require a separate query or a suffix returning STRINGS, not INTEGERS. * * @note Why not preserve types? I.e. I store integer, why do I get back a string? * Answer: types are handled different across database platforms, would cause overhead to inspect every value for type, * also PHP is a dynamically typed language so types should not matter that much. Another reason: due to the nature * of RB columns in the database might change (INT -> STRING) this would cause return types to change as well which would * cause 'cascading errors', i.e. a column gets widened and suddenly your code would break. * * @note Unfortunately the 32/64-bit issue cannot be tested fully. Return-strategy store() is probably the safest * solution. * * @return void */ public function testTypes() { testpack('Beans can only contain STRING and NULL after reload'); R::nuke(); $bean = R::dispense('bean'); $bean->number = 123; $bean->float = 12.3; $bean->bool = false; $bean->bool2 = true; $bean->text = 'abc'; $bean->null = null; $bean->datetime = new \DateTime('NOW', new \DateTimeZone('Europe/Amsterdam')); $id = R::store($bean); asrt(is_int($id), TRUE); asrt(is_float($bean->float), TRUE); asrt(is_integer($bean->number), TRUE); asrt(is_string($bean->bool), TRUE); asrt(is_string($bean->bool2), TRUE); asrt(is_string($bean->datetime), TRUE); asrt(is_string($bean->text), TRUE); asrt(is_null($bean->null), TRUE); $bean = R::load('bean', $id); asrt(is_string($bean->id), TRUE); asrt(is_string($bean->float), TRUE); asrt(is_string($bean->number), TRUE); asrt(is_string($bean->bool), TRUE); asrt(is_string($bean->bool2), TRUE); asrt(is_string($bean->datetime), TRUE); asrt(is_string($bean->text), TRUE); asrt(is_null($bean->null), TRUE); asrt($bean->bool, '0'); asrt($bean->bool2, '1'); }
/** * 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'); }
/** * Some basic tests. * * @return void */ public function testTags() { list($c, $d, $e, $f) = R::dispense('coffee', 4); R::tag($c, 'strong,black'); R::tag($d, 'black'); R::tag($e, 'strong,sweet'); R::tag($f, 'black,strong'); //$x = array_intersect(R::tagged('coffee','sweet'),R::tagged('coffee','strong')); asrt(count(R::taggedAll('coffee', 'strong,sweet')), 1); asrt(count(R::taggedAll('coffee', 'strong')), 3); asrt(count(R::taggedAll('coffee', '')), 0); asrt(count(R::taggedAll('coffee', 'sweet')), 1); asrt(count(R::taggedAll('coffee', 'sweet,strong')), 1); asrt(count(R::taggedAll('coffee', 'black,strong')), 2); asrt(count(R::taggedAll('coffee', array('black', 'strong'))), 2); asrt(count(R::taggedAll('coffee', 'salty')), 0); $blog = R::dispense('blog'); $blog->title = 'testing'; $blog->blog = 'tesing'; R::store($blog); $blogpost = R::load("blog", 1); $post = R::dispense("post"); $post->message = "hello"; R::tag($post, "lousy,smart"); asrt(implode(',', R::tag($post)), "lousy,smart"); R::tag($post, "clever,smart"); $tagz = implode(',', R::tag($post)); asrt($tagz == "smart,clever" || $tagz == "clever,smart", TRUE); R::tag($blog, array("smart", "interesting")); asrt(implode(',', R::tag($blog)), "smart,interesting"); try { R::tag($blog, array("smart", "interesting", "lousy!")); pass(); } catch (RedBean_Exception $e) { fail(); } asrt(implode(',', R::tag($blog)), "smart,interesting,lousy!"); R::untag($blog, array("smart", "interesting")); asrt(implode(",", R::tag($blog)), "lousy!"); asrt(R::hasTag($blog, array("lousy!")), TRUE); asrt(R::hasTag($blog, array("lousy!", "smart")), TRUE); asrt(R::hasTag($blog, array("lousy!", "smart"), TRUE), FALSE); R::tag($blog, FALSE); asrt(count(R::tag($blog)), 0); R::tag($blog, array("funny", "comic")); asrt(count(R::tag($blog)), 2); R::addTags($blog, array("halloween")); asrt(count(R::tag($blog)), 3); asrt(R::hasTag($blog, array("funny", "commic", "halloween"), TRUE), FALSE); R::unTag($blog, "funny"); R::addTags($blog, "horror"); asrt(count(R::tag($blog)), 3); asrt(R::hasTag($blog, array("horror", "commic", "halloween"), TRUE), FALSE); //no double tags R::addTags($blog, "horror"); asrt(R::hasTag($blog, array("horror", "commic", "halloween"), TRUE), FALSE); asrt(R::hasTag($blog, "horror,commic,halloween", TRUE), FALSE); asrt(count(R::tag($blog)), 3); testpack("fetch tagged items"); }
/** * Test usage of named parameters in SQL snippets. * Issue #299 on Github. * * @return void */ public function testNamedParamsInSnippets() { testpack('Test whether we can use named parameters in SQL snippets.'); R::nuke(); $book = R::dispense('book'); $page = R::dispense('page'); $book->title = 'book'; $book->sharedPage[] = $page; R::store($book); //should not give error like: Uncaught [HY093] - SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters $books = $page->withCondition(' title = :title ', array(':title' => 'book'))->sharedBook; asrt(count($books), 1); //should not give error... $books = $page->withCondition(' title = :title ', array(':title' => 'book'))->sharedBook; asrt(count($books), 1); R::nuke(); $book = R::dispense('book'); $page = R::dispense('page'); $book->title = 'book'; $book->comment = 'comment'; $page->title = 'page'; $book->ownPage[] = $page; R::store($book); //should also not give error.. $count = $book->countOwn('page'); asrt($count, 1); $book = $book->fresh(); //should also not give error.. $count = $book->withCondition(' title = ? ', array('page'))->countOwn('page'); asrt($count, 1); $book = $book->fresh(); //should also not give error.. $count = $book->withCondition(' title = :title ', array(':title' => 'page'))->countOwn('page'); asrt($count, 1); $book = $book->fresh(); $pages = $book->withCondition(' title = :title ', array(':title' => 'page'))->ownPage; asrt(count($pages), 1); //test with duplicate slots... $page = reset($pages); $page2 = R::dispense('page'); $page2->ownPage[] = $page; R::store($page2); $page2 = $page2->fresh(); $pages = $page2->withCondition(' title = :title ', array(':title' => 'page'))->ownPage; asrt(count($pages), 1); //test with find() $books = R::getRedBean()->find('book', array('title' => array('book')), ' AND title = :title ', array(':title' => 'book')); asrt(count($books), 1); $books = R::getRedBean()->find('book', array('title' => array('book', 'book2'), 'comment' => array('comment', 'comment2')), ' AND title = :title ', array(':title' => 'book')); asrt(count($books), 1); //just check numeric works as well... $books = R::getRedBean()->find('book', array('title' => array('book', 'book2'), 'comment' => array('comment', 'comment2')), ' AND title = ? ', array('book')); asrt(count($books), 1); //just extra check to verify glue works $books = R::getRedBean()->find('book', array('title' => array('book', 'book2'), 'comment' => array('comment', 'comment2')), ' ORDER BY id '); asrt(count($books), 1); }
/** * Test missing bean scenarios. * * @return void */ public function testMissingBeans() { testpack('deal with missing beans'); $id = R::store(R::dispense('beer')); $bottles = R::batch('beer', array($id, $id + 1, $id + 2)); asrt(count($bottles), 3); asrt((int) $bottles[$id]->id, (int) $id); asrt((int) $bottles[$id + 1]->id, 0); asrt((int) $bottles[$id + 2]->id, 0); }
/** * 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 RedBean_OODBBean, TRUE); } $listOfMeals = implode(',', R::gatherLabels($meals)); asrt($listOfMeals, 'fish,meat,vegetarian'); }
/** * Test to make sure stash cache works with recursively opening models * with FUSE. * * @return void */ public function testIssue259() { testpack('Testing Issue #259 - Stash Cache breaks model delegation in open().'); $mother = R::dispense('mother'); $mother->desc = 'I am mother'; R::store($mother); $child = R::dispense('child'); $child->mother = $mother; $child->desc = 'I am child'; $id = R::store($child); R::findOne('child', ' id = ?', array($id)); R::find('child', ' id = ? ', array($id)); R::load('child', $id); }
/** * 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 = new RedBean_OODBBean(); $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 if we can dynamically extend the R-facade. * * @return void */ public function testDynamicPlugins() { testpack('Test dynamic plugins'); //basic behaviour 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.'); } try { R::__callStatic('---', function () { }); fail(); } catch (RedException $e) { asrt($e->getMessage(), 'Plugin name may only contain alphanumeric characters.'); } try { R::invalidMethod(); fail(); } catch (RedException $e) { asrt($e->getMessage(), 'Plugin \'invalidMethod\' does not exist, add this plugin using: R::ext(\'invalidMethod\')'); } }
/** * Test count and wipe. * * @return void */ public function testCountAndWipe() { testpack("Test count and wipe"); $page = R::dispense("page"); $page->name = "ABC"; R::store($page); $n1 = R::count("page"); $page = R::dispense("page"); $page->name = "DEF"; R::store($page); $n2 = R::count("page"); asrt($n1 + 1, $n2); R::wipe("page"); asrt(R::count("page"), 0); asrt(R::getRedBean()->count("page"), 0); asrt(R::getRedBean()->count("kazoo"), 0); // non existing table R::freeze(TRUE); asrt(R::getRedBean()->count("kazoo"), 0); // non existing table R::freeze(FALSE); $page = R::dispense('page'); $page->name = 'foo'; R::store($page); $page = R::dispense('page'); $page->name = 'bar'; R::store($page); asrt(R::count('page', ' name = ? ', array('foo')), 1); // Now count something that does not exist, this should return 0. (just be polite) asrt(R::count('teapot', ' name = ? ', array('flying')), 0); asrt(R::count('teapot'), 0); $currentDriver = $this->currentlyActiveDriverID; // Some drivers don't support that many error codes. if ($currentDriver === 'mysql' || $currentDriver === 'postgres') { try { R::count('teaport', ' for tea '); fail(); } catch (SQL $e) { pass(); } } }
/** * Tests whether we can store an empty bean. * An empty bean has no properties, only ID. Normally we would * skip the ID field in an INSERT, this test forces the driver * to specify a value for the ID field. Different writers have to * use different values: Mysql uses NULL to insert a new auto-generated ID, * while Postgres has to use DEFAULT. */ public function testEmptyBean() { testpack('Test Empty Bean Storage.'); R::nuke(); $bean = R::dispense('emptybean'); $id = R::store($bean); asrt($id > 0, TRUE); asrt(R::count('emptybean'), 1); $bean = R::dispense('emptybean'); $id = R::store($bean); asrt($id > 0, TRUE); asrt(R::count('emptybean'), 2); //also test in frozen mode R::freeze(TRUE); $bean = R::dispense('emptybean'); $id = R::store($bean); asrt($id > 0, TRUE); asrt(R::count('emptybean'), 3); R::freeze(FALSE); }
/** * Test parameter binding. * * @return void */ public function testParamBindingWithPostgres() { testpack("param binding pgsql"); $page = R::dispense("page"); $page->name = "abc"; $page->number = 2; R::store($page); R::exec("insert into page (name) values(:name) ", array(":name" => "my name")); R::exec("insert into page (number) values(:one) ", array(":one" => 1)); R::exec("insert into page (number) values(:one) ", array(":one" => "1")); R::exec("insert into page (number) values(:one) ", array(":one" => "1234")); R::exec("insert into page (number) values(:one) ", array(":one" => "-21")); pass(); testpack('Test whether we can properly bind and receive NULL values'); $adapter = R::$adapter; asrt($adapter->getCell('SELECT TEXT( :nil ) ', array(':nil' => 'NULL')), 'NULL'); asrt($adapter->getCell('SELECT TEXT( :nil ) ', array(':nil' => NULL)), NULL); asrt($adapter->getCell('SELECT TEXT( ? ) ', array('NULL')), 'NULL'); asrt($adapter->getCell('SELECT TEXT( ? ) ', array(NULL)), NULL); }
/** * Test whether we have two different exception messages for * properties and values. * * @return void */ public function testIssue303() { testpack('Testing Issue #303 - Test splitting bean exception property/value.'); try { R::store(R::dispense('invalidbean')->setAttr('invalid.property', 'value')); fail(); } catch (RedException $e) { asrt($e->getMessage(), 'Invalid Bean property: property invalid.property'); } try { R::store(R::dispense('invalidbean')->setAttr('property', array())); fail(); } catch (RedException $e) { asrt($e->getMessage(), 'Invalid Bean value: property property'); } try { R::store(R::dispense('invalidbean')->setAttr('property', new \stdClass())); fail(); } catch (RedException $e) { asrt($e->getMessage(), 'Invalid Bean value: property property'); } }
/** * Test parameter binding with SQLite. * * @return void */ public function testParamBindWithSQLite() { $toolbox = R::$toolbox; $adapter = $toolbox->getDatabaseAdapter(); $writer = $toolbox->getWriter(); $redbean = $toolbox->getRedBean(); $pdo = $adapter->getDatabase(); asrt((int) $adapter->getCell("SELECT 123"), 123); asrt((int) $adapter->getCell("SELECT ?", array("987")), 987); asrt((int) $adapter->getCell("SELECT ?+?", array("987", "2")), 989); asrt((int) $adapter->getCell("SELECT :numberOne+:numberTwo", array(":numberOne" => 42, ":numberTwo" => 50)), 92); $pair = $adapter->getAssoc("SELECT 'thekey','thevalue' "); asrt(is_array($pair), TRUE); asrt(count($pair), 1); asrt(isset($pair["thekey"]), TRUE); asrt($pair["thekey"], "thevalue"); testpack('Test whether we can properly bind and receive NULL values'); asrt($adapter->getCell('SELECT :nil ', array(':nil' => 'NULL')), 'NULL'); asrt($adapter->getCell('SELECT :nil ', array(':nil' => NULL)), NULL); asrt($adapter->getCell('SELECT ? ', array('NULL')), 'NULL'); asrt($adapter->getCell('SELECT ? ', array(NULL)), NULL); }
/** * Test meta data methods. * * @return void */ public function testMetaData() { testpack('Test meta data'); $bean = new RedBean_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 RedBean_OODBBean(); $bean->setMeta("meta.meta", "123"); $bean2 = new RedBean_OODBBean(); asrt($bean2->getMeta("meta.meta"), NULL); $bean2->copyMetaFrom($bean); asrt($bean2->getMeta("meta.meta"), "123"); }
asrt(setget("a"), "a"); asrt(setget("."), "."); asrt(setget("\""), "\""); asrt(setget("just some text"), "just some text"); asrt(setget(true), "1"); asrt(setget(false), "0"); asrt(setget("true"), "true"); asrt(setget("false"), "false"); asrt(setget("null"), "null"); asrt(setget("NULL"), "NULL"); asrt(setget(null), null); asrt(setget(0) == 0, true); asrt(setget(1) == 1, true); asrt(setget(true) == true, true); asrt(setget(false) == false, true); testpack("test views"); class Fm implements RedBean_IBeanFormatter { public function formatBeanTable($table) { return "prefix_{$table}"; } public function formatBeanID($table) { return $table . "__id"; } public function getAlias($a) { return '__'; } }
/** * Test special data types. * * @return void */ public function testSpecialDataTypes() { testpack('Special data types'); $bean = R::dispense('bean'); $bean->date = 'someday'; R::store($bean); $cols = R::getColumns('bean'); asrt($cols['date'], 'TEXT'); $bean = R::dispense('bean'); $bean->date = '2011-10-10'; R::nuke(); $bean = R::dispense('bean'); $bean->date = '2011-10-10'; R::store($bean); $cols = R::getColumns('bean'); asrt($cols['date'], 'NUMERIC'); }
/** * Test special types. * * @return void */ public function testTypes() { testpack('Special data types'); $bean = R::dispense('bean'); $bean->date = 'someday'; R::store($bean); $cols = R::getColumns('bean'); asrt($cols['date'], 'text'); $bean = R::dispense('bean'); $bean->date = '2011-10-10'; R::store($bean); $cols = R::getColumns('bean'); asrt($cols['date'], 'text'); }
<?php /** * Pretest * * These tests will run before the configuration takes place * in the unit test suite (mostly error handling tests). * * @file RedUNIT/Pretest.php * @desc Test scripts that run before configuration * @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. */ testpack('Running pre-tests. (before config).'); try { R::debug(TRUE); fail(); } catch (Exception $e) { pass(); } asrt(R::testConnection(), FALSE); R::addDatabase('broken', 'mysql:host=nowhere', 'defunct', 'void'); R::selectDatabase('broken'); asrt(R::testConnection(), FALSE);
/** * Test single column bases unique constraints. * * @return void */ public function testSingleColUniqueConstraint() { testpack('Testing unique constraint on single column'); //mysql cant handle this due to utf8mb4 fuckup Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes if ($this->currentlyActiveDriverID === 'mysql') { return; } $book = R::dispense('book'); $book->setMeta('buildcommand.unique', array(array('title'))); $book->title = 'bla'; $book->extra = 2; $id = R::store($book); $book = R::dispense('book'); $book->title = 'bla'; $expected = NULL; try { R::store($book); fail(); } catch (RedBean_Exception_SQL $e) { $expected = $e; } asrt($expected instanceof RedBean_Exception_SQL, TRUE); asrt(R::count('book'), 1); $book = R::load('book', $id); // Causes failure, table will be rebuild $book->extra = 'CHANGE'; $id2 = R::store($book); $book2 = R::load('book', $id2); $book = R::dispense('book'); $book->title = 'bla'; try { R::store($book); fail(); } catch (RedBean_Exception_SQL $e) { $expected = $e; } asrt($expected instanceof RedBean_Exception_SQL, TRUE); asrt(R::count('book'), 1); }
/** * Test explicit flush. * * @return void */ public function testExplicitCacheFlush() { testpack('Test cache flush (explicit)'); R::debug(true, 1); $logger = R::getDatabaseAdapter()->getDatabase()->getLogger(); $bean = R::dispense('bean'); $bean->title = 'abc'; $id1 = R::store($bean); $logger->clear(); $bean = R::load('bean', $id1); asrt($bean->title, 'abc'); asrt(count($logger->grep('SELECT *')), 1); $bean = R::load('bean', $id1); asrt(count($logger->grep('SELECT *')), 1); R::getWriter()->flushCache(); $bean = R::load('bean', $id1); asrt(count($logger->grep('SELECT *')), 2); R::getWriter()->flushCache(); R::getWriter()->setUseCache(FALSE); }
/** * Test widen for constraint. * * @return void */ public function testWideningColumnForConstraint() { testpack('widening column for constraint'); $bean1 = R::dispense('project'); $bean2 = R::dispense('invoice'); R::setStrictTyping(FALSE); $bean3 = R::dispense('invoice_project'); R::setStrictTyping(TRUE); $bean3->project_id = 1; $bean3->invoice_id = 2; R::store($bean3); $cols = R::getColumns('invoice_project'); asrt($cols['project_id'], "tinyint(1) unsigned"); asrt($cols['invoice_id'], "tinyint(3) unsigned"); R::$writer->addConstraint($bean1, $bean2); $cols = R::getColumns('invoice_project'); asrt($cols['project_id'], "int(11) unsigned"); asrt($cols['invoice_id'], "int(11) unsigned"); }
/** * Test widen for constraint. * * @return void */ public function testWideningColumnForConstraint() { testpack('widening column for constraint'); $bean1 = R::dispense('project'); $bean2 = R::dispense('invoice'); $bean3 = R::getRedBean()->dispense('invoice_project'); $bean3->project_id = false; $bean3->invoice_id = true; R::store($bean3); $cols = R::getColumns('invoice_project'); asrt($cols['project_id'], "int(11) unsigned"); asrt($cols['invoice_id'], "int(11) unsigned"); }
/** * Test trashAll(). */ public function testMultiDeleteUpdate() { testpack('test multi delete and multi update'); $beans = R::dispenseLabels('bean', array('a', 'b')); $ids = R::storeAll($beans); asrt((int) R::count('bean'), 2); R::trashAll(R::batch('bean', $ids)); asrt((int) R::count('bean'), 0); testpack('test assocManager check'); $rb = new OODB(R::getWriter()); try { $rb->getAssociationManager(); fail(); } catch (RedException $e) { pass(); } }
/** * All kinds of tests for basic CRUD. * * Does the data survive? * * @return void */ public function testUpdatingBeans() { testpack('Test basic support UUID/override ID default value'); $bean = R::dispense('bean'); R::store($bean); if ($this->currentlyActiveDriverID === 'mysql') { //otherwise UTF8 causes index overflow in mysql: SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes R::exec('alter table bean modify column id char(3);'); } else { R::getWriter()->widenColumn('bean', 'id', R::getWriter()->scanType('abc')); } $bean->id = 'abc'; R::store($bean); asrt($bean->id, 'abc'); testpack('Test Update'); try { R::store(array()); fail(); } catch (RedException $e) { pass(); } $toolbox = R::getToolBox(); $adapter = $toolbox->getDatabaseAdapter(); $writer = $toolbox->getWriter(); $redbean = $toolbox->getRedBean(); $pdo = $adapter->getDatabase(); $page = $redbean->dispense("page"); $page->name = "old name"; $id = $redbean->store($page); asrt($page->getMeta('tainted'), FALSE); $page->setAttr('name', "new name"); asrt($page->getMeta('tainted'), TRUE); $id = $redbean->store($page); $page = $redbean->load("page", $id); asrt($page->name, "new name"); // Null should == NULL after saving $page->rating = NULL; $newid = $redbean->store($page); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt($page->rating === NULL, TRUE); asrt(!$page->rating, TRUE); $page->rating = FALSE; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt((bool) $page->rating, FALSE); asrt($page->rating == FALSE, TRUE); asrt(!$page->rating, TRUE); $page->rating = TRUE; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt((bool) $page->rating, TRUE); asrt($page->rating == TRUE, TRUE); asrt($page->rating == TRUE, TRUE); $page->rating = NULL; R::store($page); $page = R::load('page', $page->id); asrt($page->rating, NULL); $page->rating = "1"; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt($page->rating, "1"); $page->rating = "0"; $newid = $redbean->store($page); asrt($page->rating, "0"); $page->rating = 0; $newid = $redbean->store($page); asrt($page->rating, 0); $page->rating = "0"; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt(!$page->rating, TRUE); asrt($page->rating == 0, TRUE); asrt($page->rating == FALSE, TRUE); $page->rating = 5; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt(strval($page->rating), "5"); $page->rating = 300; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt(strval($page->rating), "300"); $page->rating = -2; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt(strval($page->rating), "-2"); $page->rating = 2.5; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt($page->rating == 2.5, TRUE); $page->rating = -3.3; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt($page->rating == -3.3, TRUE); $page->rating = "good"; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt($page->rating, "good"); $longtext = str_repeat('great! because..', 100); $page->rating = $longtext; $newid = $redbean->store($page); asrt($newid, $id); $page = $redbean->load("page", $id); asrt($page->name, "new name"); asrt($page->rating, $longtext); // Test leading zeros $numAsString = "0001"; $page->numasstring = $numAsString; $redbean->store($page); $page = $redbean->load("page", $id); asrt($page->numasstring, "0001"); $page->numnotstring = "0.123"; $redbean->store($page); $page = $redbean->load("page", $id); asrt($page->numnotstring == 0.123, TRUE); $page->numasstring2 = "00.123"; $redbean->store($page); $page = $redbean->load("page", $id); asrt($page->numasstring2, "00.123"); try { $redbean->trash(array()); fail(); } catch (RedException $e) { pass(); } $redbean->trash($page); asrt((int) $pdo->GetCell("SELECT count(*) FROM page"), 0); }
/** * 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); }
/** * Test tree traversal with searchIn(). * * @return void */ public function testTreeTraversal() { testpack('Test Tree Traversal'); R::nuke(); $page = R::dispense('page', 10); //Setup the test data for this series of tests $i = 0; foreach ($page as $pageItem) { $pageItem->name = 'page' . $i; $pageItem->number = $i; $i++; R::store($pageItem); } $page[0]->ownPage = array($page[1], $page[2]); $page[1]->ownPage = array($page[3], $page[4]); $page[3]->ownPage = array($page[5]); $page[5]->ownPage = array($page[7]); $page[9]->document = $page[8]; $page[9]->book = R::dispense('book'); R::store($page[9]); $id = R::store($page[0]); $book = $page[9]->book; }
$pdo->Execute("DROP TABLE IF EXISTS book"); $pdo->Execute("DROP TABLE IF EXISTS author"); $pdo->Execute("DROP TABLE IF EXISTS book_author"); $pdo->Execute("DROP TABLE IF EXISTS author_book"); $redbean = $toolbox->getRedBean(); $a = new RedBean_AssociationManager($toolbox); $book = $redbean->dispense("book"); $author1 = $redbean->dispense("author"); $author2 = $redbean->dispense("author"); $book->title = "My First Post"; $author1->name = "Derek"; $author2->name = "Whoever"; $a->associate($book, $author1); $a->associate($book, $author2); pass(); testpack("Test Association Issue Group keyword (Issues 9 and 10)"); $pdo->Execute("DROP TABLE IF EXISTS `group`"); $pdo->Execute("DROP TABLE IF EXISTS `book_group`"); $group = $redbean->dispense("group"); $group->name = "mygroup"; $redbean->store($group); try { $a->associate($group, $book); pass(); } catch (RedBean_Exception_SQL $e) { fail(); } //test issue SQL error 23000 try { $a->associate($group, $book); pass();
/** * Test parameter binding with\PDO. * * @return void */ public function testPDOParameterBinding() { $toolbox = R::getToolBox(); $adapter = $toolbox->getDatabaseAdapter(); $writer = $toolbox->getWriter(); $redbean = $toolbox->getRedBean(); $pdo = $adapter->getDatabase(); R::getDatabaseAdapter()->getDatabase()->setUseStringOnlyBinding(TRUE); try { R::getAll("select * from job limit ? ", array(1)); fail(); } catch (\Exception $e) { pass(); } try { R::getAll("select * from job limit :l ", array(":l" => 1)); fail(); } catch (\Exception $e) { pass(); } try { R::exec("select * from job limit ? ", array(1)); fail(); } catch (\Exception $e) { pass(); } try { R::exec("select * from job limit :l ", array(":l" => 1)); fail(); } catch (\Exception $e) { pass(); } R::getDatabaseAdapter()->getDatabase()->setUseStringOnlyBinding(FALSE); try { R::getAll("select * from job limit ? ", array(1)); pass(); } catch (\Exception $e) { print_r($e); fail(); } try { R::getAll("select * from job limit :l ", array(":l" => 1)); pass(); } catch (\Exception $e) { fail(); } try { R::exec("select * from job limit ? ", array(1)); pass(); } catch (\Exception $e) { fail(); } try { R::exec("select * from job limit :l ", array(":l" => 1)); pass(); } catch (\Exception $e) { fail(); } testpack("Test findOrDispense"); $person = R::findOrDispense("person", " job = ? ", array("developer")); asrt(count($person) > 0, TRUE); $person = R::findOrDispense("person", " job = ? ", array("musician")); asrt(count($person) > 0, TRUE); $musician = array_pop($person); asrt(intval($musician->id), 0); try { $adapter->exec("an invalid query"); fail(); } catch (SQL $e) { pass(); } asrt((int) $adapter->getCell("SELECT 123"), 123); asrt((int) $adapter->getCell("SELECT ?", array("987")), 987); asrt((int) $adapter->getCell("SELECT ?+?", array("987", "2")), 989); asrt((int) $adapter->getCell("SELECT :numberOne+:numberTwo", array(":numberOne" => 42, ":numberTwo" => 50)), 92); $pair = $adapter->getAssoc("SELECT 'thekey','thevalue' "); asrt(is_array($pair), TRUE); asrt(count($pair), 1); asrt(isset($pair["thekey"]), TRUE); asrt($pair["thekey"], "thevalue"); testpack('Test whether we can properly bind and receive NULL values'); asrt($adapter->getCell('SELECT :nil ', array(':nil' => 'NULL')), 'NULL'); asrt($adapter->getCell('SELECT :nil ', array(':nil' => NULL)), NULL); asrt($adapter->getCell('SELECT ? ', array('NULL')), 'NULL'); asrt($adapter->getCell('SELECT ? ', array(NULL)), NULL); }
/** * ExportAll. * * @return void */ public function testExportAll() { testpack('Test exportAll'); $redbean = R::getRedBean(); $bean = new OODBBean(); $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); }