Yaffs site version 1.1
[yaffs-website] / vendor / gabordemooij / redbean / testing / RedUNIT / Base / Misc.php
1 <?php
2
3 namespace RedUNIT\Base;
4
5 use RedUNIT\Base as Base;
6 use RedBeanPHP\Facade as R;
7 use RedBeanPHP\Logger\RDefault as RDefault;
8 use RedBeanPHP\Logger as Logger;
9 use RedBeanPHP\OODBBean as OODBBean;
10 use RedBeanPHP\OODB as OODB;
11 use RedBeanPHP\Adapter as Adapter;
12 use RedBeanPHP\QueryWriter as QueryWriter;
13 use RedBeanPHP\RedException as RedException;
14 use RedBeanPHP\RedException\SQL as SQL;
15 use RedBeanPHP\Driver\RPDO as RPDO;
16 use RedBeanPHP\SimpleModel as SimpleModel;
17
18 /**
19  * Misc
20  *
21  * @file    RedUNIT/Base/Misc.php
22  * @desc    Various tests.
23  * @author  Gabor de Mooij and the RedBeanPHP Community
24  * @license New BSD/GPLv2
25  *
26  * (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community.
27  * This source file is subject to the New BSD/GPLv2 License that is bundled
28  * with this source code in the file license.txt.
29  */
30 class Misc extends Base
31 {
32         /**
33          * Test whether we can set the 'auto clear'
34          * option in OODB.
35          *
36          * @return void
37          */
38         public function testAutoClearHistory()
39         {
40                 testpack( 'Auto clear history' );
41                 $book = R::dispense( 'book' );
42                 $book->pages = 100;
43                 $book->title = 'book';
44                 R::store( $book );
45                 $book = R::findOne( 'book' );
46                 asrt( $book->hasChanged( 'title' ), FALSE );
47                 $book->title = 'yes';
48                 R::store( $book );
49                 asrt( $book->hasChanged( 'title' ), TRUE );
50                 OODB::autoClearHistoryAfterStore( TRUE );
51                 $book = R::findOne( 'book' );
52                 asrt( $book->hasChanged( 'title' ), FALSE );
53                 $book->title = 'yes2';
54                 R::store( $book );
55                 asrt( $book->hasChanged( 'title' ), FALSE );
56                 OODB::autoClearHistoryAfterStore( FALSE );
57                 $book = R::findOne( 'book' );
58                 asrt( $book->hasChanged( 'title' ), FALSE );
59                 $book->title = 'yes';
60                 R::store( $book );
61                 asrt( $book->hasChanged( 'title' ), TRUE );
62         }
63
64         /**
65         * Tests the R::inspect() method on the Facade.
66         *
67         * @return void
68         */
69         public function testInspect() {
70
71                 testpack( 'Test R::inspect() ' );
72                 R::nuke();
73                 R::store( R::dispense( 'book' )->setAttr( 'title', 'book' ) );
74                 $info = R::inspect();
75                 asrt( count( $info ), 1 );
76                 asrt( strtolower( $info[0] ), 'book' );
77                 $info = R::inspect( 'book' );
78                 asrt( count( $info ), 2 );
79                 $keys = array_keys( $info );
80                 sort($keys);
81                 asrt( strtolower( $keys[0] ), 'id' );
82                 asrt( strtolower( $keys[1] ), 'title' );
83         }
84
85         /**
86          * Test whether we can use the tableExist() method in OODB
87          * instances directly to help us determine
88          * the existance of a table.
89          *
90          * @return void
91          */
92         public function testTableExist()
93         {
94                 R::nuke();
95                 R::store( R::dispense( 'book' ) );
96                 R::freeze( FALSE );
97                 asrt( R::getRedBean()->tableExists( 'book' ), TRUE );
98                 asrt( R::getRedBean()->tableExists( 'book2' ), FALSE );
99                 R::freeze( TRUE );
100                 asrt( R::getRedBean()->tableExists( 'book' ), TRUE );
101                 asrt( R::getRedBean()->tableExists( 'book2' ), FALSE );
102                 R::freeze( FALSE );
103         }
104
105         /**
106          * Normally the check() method is always called indirectly when
107          * dealing with beans. This test ensures we can call check()
108          * directly. Even though frozen repositories do not rely on
109          * bean checking to improve performance the method should still
110          * offer the same functionality when called directly.
111          *
112          * @return void
113          */
114         public function testCheckDirectly()
115         {
116                 $bean = new OODBBean;
117                 $bean->id = 0;
118                 $bean->setMeta( 'type', 'book' );
119                 R::getRedBean()->check( $bean );
120                 $bean->setMeta( 'type', '.' );
121                 try {
122                         R::getRedBean()->check( $bean );
123                         fail();
124                 } catch ( \Exception $e ) {
125                         pass();
126                 }
127                 //check should remain the same even if frozen repo is used, method is public after all!
128                 //we dont want to break the API!
129                 R::freeze( TRUE );
130                 try {
131                         R::getRedBean()->check( $bean );
132                         fail();
133                 } catch ( \Exception $e ) {
134                         pass();
135                 }
136                 R::freeze( FALSE );
137         }
138
139         /**
140          * Test Backward compatibility writer ESC-method.
141          *
142          * @return void
143          */
144         public function testLegacyCode()
145         {
146                 testpack( 'Test Backward compatibility methods in writer.' );
147                 asrt( R::getWriter()->safeColumn( 'column', TRUE ), R::getWriter()->esc( 'column', TRUE ) );
148                 asrt( R::getWriter()->safeColumn( 'column', FALSE ), R::getWriter()->esc( 'column', FALSE ) );
149                 asrt( R::getWriter()->safeTable( 'table', TRUE ), R::getWriter()->esc( 'table', TRUE ) );
150                 asrt( R::getWriter()->safeTable( 'table', FALSE ), R::getWriter()->esc( 'table', FALSE ) );
151         }
152
153         /**
154          * Test beautification and array functions.
155          *
156          * @return void
157          */
158         public function testBeauficationAndArrayFunctions()
159         {
160                 $bean = R::dispense( 'bean' );
161                 $bean->isReallyAwesome = TRUE;
162                 asrt( isset( $bean->isReallyAwesome ), TRUE );
163                 asrt( isset( $bean->is_really_awesome ), TRUE );
164                 unset( $bean->is_really_awesome );
165                 asrt( isset( $bean->isReallyAwesome ), FALSE );
166                 asrt( isset( $bean->is_really_awesome ), FALSE );
167         }
168
169         /**
170          * Test beautification of column names.
171          *
172          * @return void
173          */
174         public function testBeautifulColumnNames()
175         {
176                 testpack( 'Beautiful column names' );
177                 $town = R::dispense( 'town' );
178                 $town->isCapital       = FALSE;
179                 $town->hasTrainStation = TRUE;
180                 $town->name            = 'BeautyVille';
181                 $houses = R::dispense( 'house', 2 );
182                 $houses[0]->isForSale = TRUE;
183                 $town->ownHouse = $houses;
184                 R::store( $town );
185                 $town = R::load( 'town', $town->id );
186                 asrt( ( $town->isCapital == FALSE ), TRUE );
187                 asrt( ( $town->hasTrainStation == TRUE ), TRUE );
188                 asrt( ( $town->name == 'BeautyVille' ), TRUE );
189                 testpack( 'Accept datetime objects.' );
190                 $cal = R::dispense( 'calendar' );
191                 $cal->when = new\DateTime( '2000-01-01', new\DateTimeZone( 'Pacific/Nauru' ) );
192                 asrt( $cal->when, '2000-01-01 00:00:00' );
193                 testpack( 'Affected rows test' );
194                 $currentDriver = $this->currentlyActiveDriverID;
195                 $toolbox = R::getToolBox();
196                 $adapter = $toolbox->getDatabaseAdapter();
197                 $writer  = $toolbox->getWriter();
198                 $redbean = $toolbox->getRedBean();
199                 $pdo     = $adapter->getDatabase();
200                 $bean = $redbean->dispense( 'bean' );
201                 $bean->prop = 3; //make test run with strict mode as well
202                 $redbean->store( $bean );
203                 $adapter->exec( 'UPDATE bean SET prop = 2' );
204                 asrt( $adapter->getAffectedRows(), 1 );
205                 testpack( 'Testing Logger' );
206                 R::getDatabaseAdapter()->getDatabase()->setLogger( new RDefault );
207                 asrt( ( R::getDatabaseAdapter()->getDatabase()->getLogger() instanceof Logger ), TRUE );
208                 asrt( ( R::getDatabaseAdapter()->getDatabase()->getLogger() instanceof RDefault ), TRUE );
209                 $bean = R::dispense( 'bean' );
210                 $bean->property = 1;
211                 $bean->unsetAll( array( 'property' ) );
212                 asrt( $bean->property, NULL );
213                 asrt( ( $bean->setAttr( 'property', 2 ) instanceof OODBBean ), TRUE );
214                 asrt( $bean->property, 2 );
215                 asrt( preg_match( '/\d\d\d\d\-\d\d\-\d\d/', R::isoDate() ), 1 );
216                 asrt( preg_match( '/\d\d\d\d\-\d\d\-\d\d\s\d\d:\d\d:\d\d/', R::isoDateTime() ), 1 );
217                 $redbean = R::getRedBean();
218                 $adapter = R::getDatabaseAdapter();
219                 $writer  = R::getWriter();
220                 asrt( ( $redbean instanceof OODB ), TRUE );
221                 asrt( ( $adapter instanceof Adapter ), TRUE );
222                 asrt( ( $writer instanceof QueryWriter ), TRUE );
223                 R::setRedBean( $redbean );
224                 pass(); //cant really test this
225                 R::setDatabaseAdapter( $adapter );
226                 pass(); //cant really test this
227                 R::setWriter( $writer );
228                 pass(); //cant really test this
229                 $u1 = R::dispense( 'user' );
230                 $u1->name  = 'Gabor';
231                 $u1->login = 'g';
232                 $u2 = R::dispense( 'user' );
233                 $u2->name  = 'Eric';
234                 $u2->login = 'e';
235                 R::store( $u1 );
236                 R::store( $u2 );
237                 $list = R::getAssoc( 'select login,' . R::getWriter()->esc( 'name' ) . ' from ' . R::getWriter()->esc( 'user' ) . ' ' );
238                 asrt( $list['e'], 'Eric' );
239                 asrt( $list['g'], 'Gabor' );
240                 $painting = R::dispense( 'painting' );
241                 $painting->name = 'Nighthawks';
242                 $id = R::store( $painting );
243                 testpack( 'Testing SQL Error Types' );
244                 foreach ( $writer->typeno_sqltype as $code => $text ) {
245                         asrt( is_integer( $code ), TRUE );
246                         asrt( is_string( $text ), TRUE );
247                 }
248                 foreach ( $writer->sqltype_typeno as $text => $code ) {
249                         asrt( is_integer( $code ), TRUE );
250                         asrt( is_string( $text ), TRUE );
251                 }
252                 testpack( 'Testing Nowhere Pt. 1 (unfrozen)' );
253                 foreach (
254                         array(
255                                 'exec', 'getAll', 'getCell', 'getAssoc', 'getRow', 'getCol'
256                         )
257                         as $method ) {
258                         R::$method( 'select * from nowhere' );
259                         pass();
260                 }
261                 testpack( 'Testing Nowhere Pt. 2 (frozen)' );
262                 R::freeze( TRUE );
263                 foreach (
264                         array(
265                                 'exec', 'getAll', 'getCell', 'getAssoc', 'getRow', 'getCol'
266                         )
267                         as $method ) {
268                         try {
269                                 R::$method( 'select * from nowhere' );
270                                 fail();
271                         } catch ( SQL $e ) {
272                                 pass();
273                         }
274                 }
275                 R::freeze( FALSE );
276         }
277
278         /**
279          * Test reflectional functions of database.
280          *
281          * @return void
282          */
283         public function testDatabaseProperties()
284         {
285                 testpack( 'Testing Database Properties' );
286                 $adapter = R::getDatabaseAdapter();
287                 if ( method_exists( R::getDatabaseAdapter()->getDatabase(), 'getPDO' ) ){
288                         asrt( $adapter->getDatabase()->getPDO() instanceof \PDO, TRUE );
289                 }
290                 asrt( strlen( $adapter->getDatabase()->getDatabaseVersion() ) > 0, TRUE );
291                 asrt( strlen( $adapter->getDatabase()->getDatabaseType() ) > 0, TRUE );
292         }
293
294         /**
295          * Test Transactions.
296          *
297          * @return void
298          */
299         public function testTransactions()
300         {
301                 testpack( 'transactions' );
302                 R::begin();
303                 $bean = R::dispense( 'bean' );
304                 R::store( $bean );
305                 R::commit();
306                 asrt( R::count( 'bean' ), 1 );
307                 R::wipe( 'bean' );
308                 R::freeze( 1 );
309                 R::begin();
310                 $bean = R::dispense( 'bean' );
311                 R::store( $bean );
312                 R::rollback();
313                 asrt( R::count( 'bean' ), 0 );
314                 R::freeze( FALSE );
315                 testpack( 'genSlots' );
316                 asrt( R::genSlots( array( 'a', 'b' ) ), '?,?' );
317                 asrt( R::genSlots( array( 'a' ) ), '?' );
318                 asrt( R::genSlots( array() ), '' );
319         }
320
321         /**
322          * Test nested FUSE scenarios.
323          *
324          * @return void
325          */
326         public function testFUSEnested()
327         {
328                 testpack( 'FUSE models cant touch nested beans in update() - issue 106' );
329                 $spoon       = R::dispense( 'spoon' );
330                 $spoon->name = 'spoon for test bean';
331                 $deep        = R::dispense( 'deep' );
332                 $deep->name  = 'deepbean';
333                 $item        = R::dispense( 'item' );
334                 $item->val   = 'Test';
335                 $item->deep  = $deep;
336                 $test = R::dispense( 'test' );
337                 $test->item          = $item;
338                 $test->sharedSpoon[] = $spoon;
339                 $test->isnowtainted = TRUE;
340                 $id   = R::store( $test );
341                 $test = R::load( 'test', $id );
342                 asrt( $test->item->val, 'Test2' );
343                 $can   = reset( $test->ownCan );
344                 $spoon = reset( $test->sharedSpoon );
345                 asrt( $can->name, 'can for bean' );
346                 asrt( $spoon->name, 'S2' );
347                 asrt( $test->item->deep->name, '123' );
348                 asrt( count( $test->ownCan ), 1 );
349                 asrt( count( $test->sharedSpoon ), 1 );
350                 asrt( count( $test->sharedPeas ), 10 );
351                 asrt( count( $test->ownChip ), 9 );
352         }
353
354         /**
355          * Tests FUSE and lists, FUSE enforces no more than
356          * 3 sugar cubes in coffee.
357          *
358          * @return void
359          */
360         public function testCoffeeWithSugarAndFUSE()
361         {
362                 $coffee = R::dispense( 'coffee' );
363                 $coffee->size     = 'XL';
364                 $coffee->ownSugar = R::dispense( 'sugar', 5 );
365                 $id = R::store( $coffee );
366                 $coffee = R::load( 'coffee', $id );
367                 asrt( count( $coffee->ownSugar ), 3 );
368                 $coffee->ownSugar = R::dispense( 'sugar', 2 );
369                 $id     = R::store( $coffee );
370                 $coffee = R::load( 'coffee', $id );
371                 asrt( count( $coffee->ownSugar ), 2 );
372                 $cocoa = R::dispense( 'cocoa' );
373                 $cocoa->name = 'Fair Cocoa';
374                 list( $taste1, $taste2 ) = R::dispense( 'taste', 2 );
375                 $taste1->name = 'sweet';
376                 $taste2->name = 'bitter';
377                 $cocoa->ownTaste = array( $taste1, $taste2 );
378                 R::store( $cocoa );
379                 $cocoa->name = 'Koko';
380                 R::store( $cocoa );
381                 if ( method_exists( R::getDatabaseAdapter()->getDatabase(), 'getPDO' ) ) {
382                         $pdo    = R::getDatabaseAdapter()->getDatabase()->getPDO();
383                         $driver = new RPDO( $pdo );
384                         pass();
385                         asrt( $pdo->getAttribute(\PDO::ATTR_ERRMODE ),\PDO::ERRMODE_EXCEPTION );
386                         asrt( $pdo->getAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE ),\PDO::FETCH_ASSOC );
387                         asrt( strval( $driver->GetCell( 'select 123' ) ), '123' );
388                 }
389                 $a = new SQL;
390                 $a->setSqlState( 'test' );
391                 $b = strval( $a );
392                 asrt( ( strpos( $b, '[test] - ' ) === 0 ), TRUE );
393         }
394
395         /**
396         * ENUM Basic tests.
397         *
398         * @return void
399         */
400         public function testENUMBasics() {
401                 asrt( R::enum( 'gender:male' )->name, 'MALE' );
402                 asrt( R::enum( 'country:South-Africa' )->name, 'SOUTH_AFRICA' );
403                 asrt( R::enum( 'tester:T@E  S_t' )->name, 'T_E_S_T' );
404         }
405
406         /**
407          * Test ENUM in Queries and with short hand notation.
408          *
409          * @return void
410          */
411         public function testENUMInQuery()
412         {
413                 testpack('Test ENUM in Query and test ENUM short notation');
414                 R::nuke();
415                 $coffee = R::dispense( 'coffee' );
416                 $coffee->taste = R::enum( 'flavour:mocca' );
417                 R::store( $coffee );
418                 $coffee = R::dispense( 'coffee' );
419                 $coffee->taste = R::enum( 'flavour:banana' );
420                 R::store( $coffee );
421                 $coffee = R::dispense( 'coffee' );
422                 $coffee->taste = R::enum( 'flavour:banana' );
423                 R::store( $coffee );
424                 //now we have two flavours
425                 asrt( R::count('flavour'), 2 );
426                 //use in query
427                 asrt( R::count( 'coffee', ' taste_id = ? ', array( R::enum( 'flavour:mocca' )->id ) ), 1);
428                 //use in quer with short notation
429                 asrt( R::count( 'coffee', ' taste_id = ? ', array( EID( 'flavour:mocca' ) ) ), 1);
430                 //use in query
431                 asrt( R::count( 'coffee', ' taste_id = ? ', array( R::enum( 'flavour:banana' )->id ) ), 2);
432                 //use in quer with short notation
433                 asrt( R::count( 'coffee', ' taste_id = ? ', array( EID( 'flavour:banana' ) ) ), 2);
434                 //use in query
435                 asrt( R::count( 'coffee', ' taste_id = ? ', array( R::enum( 'flavour:strawberry' )->id ) ), 0);
436                 //use in quer with short notation
437                 asrt( R::count( 'coffee', ' taste_id = ? ', array( EID( 'flavour:strawberry' ) ) ), 0);
438         }
439
440         /**
441          * Test ENUM functionality offered by Label Maker.
442          *
443          * @return void
444          */
445         public function testENUM() {
446                 testpack('test ENUM');
447                 $coffee = R::dispense( 'coffee' );
448                 $coffee->taste = R::enum( 'flavour:mocca' );
449                 //did we create an enum?
450                 asrt( implode( '', R::gatherLabels( R::enum( 'flavour' ) ) ), 'MOCCA' );
451                 R::store( $coffee );
452                 $coffee = $coffee->fresh();
453                 //test enum identity check - with alias
454                 asrt( $coffee->fetchAs( 'flavour' )->taste->equals( R::enum('flavour:mocca') ), TRUE );
455                 asrt( $coffee->fetchAs( 'flavour' )->taste->equals( R::enum('flavour:banana') ), FALSE );
456                 //now we have two flavours
457                 asrt( R::count( 'flavour' ), 2 );
458                 asrt( implode( ',', R::gatherLabels( R::enum( 'flavour') ) ), 'BANANA,MOCCA' );
459                 $coffee->flavour = R::enum( 'flavour:mocca' );
460                 R::store($coffee);
461                 //same results, can we have multiple flavours?
462                 asrt( $coffee->fetchAs( 'flavour' )->taste->equals( R::enum( 'flavour:mocca' ) ), TRUE );
463                 asrt( $coffee->fetchAs( 'flavour' )->taste->equals( R::enum( 'flavour:banana' ) ), FALSE );
464                 asrt( $coffee->flavour->equals( R::enum( 'flavour:mocca' ) ), TRUE );
465                 //no additional mocca enum...
466                 asrt( R::count( 'flavour' ), 2 );
467                 $drink = R::dispense( 'drink' );
468                 $drink->flavour = R::enum( 'flavour:choco' );
469                 R::store( $drink );
470                 //now we have three!
471                 asrt( R::count('flavour'), 3 );
472                 $drink = R::load( 'drink', $drink->id );
473                 asrt( $drink->flavour->equals( R::enum('flavour:mint') ), FALSE );
474                 asrt( $drink->flavour->equals( R::enum('flavour:choco') ), TRUE );
475                 asrt( R::count( 'flavour' ), 4 );
476                 //trash should not affect flavour!
477                 R::trash( $drink );
478                 asrt( R::count( 'flavour' ), 4 );
479         }
480
481         /**
482          * Test trashAll().
483          */
484         public function testMultiDeleteUpdate()
485         {
486                 testpack( 'test multi delete and multi update' );
487                 $beans = R::dispenseLabels( 'bean', array( 'a', 'b' ) );
488                 $ids   = R::storeAll( $beans );
489                 asrt( (int) R::count( 'bean' ), 2 );
490                 R::trashAll( R::batch( 'bean', $ids ) );
491                 asrt( (int) R::count( 'bean' ), 0 );
492                 testpack( 'test assocManager check' );
493                 $rb = new OODB( R::getWriter() );
494                 try {
495                         $rb->getAssociationManager();
496                         fail();
497                 } catch ( RedException $e ) {
498                         pass();
499                 }
500         }
501
502         /**
503          * Test Bean identity equality.
504          */
505         public function testBeanIdentityEquality() {
506                 $beanA = R::dispense( 'bean' );
507                 $beanB = R::dispense( 'bean' );
508                 $beanA->id = 1;
509                 $beanB->id = 1;
510                 asrt( $beanA->equals( $beanB ), TRUE );
511                 asrt( $beanB->equals( $beanA ), TRUE );
512                 asrt( $beanA->equals( $beanA ), TRUE );
513                 asrt( $beanB->equals( $beanB ), TRUE );
514                 $beanB->id = 2;
515                 asrt( $beanA->equals( $beanB ), FALSE );
516                 asrt( $beanB->equals( $beanA ), FALSE );
517                 $beanA->id = '2';
518                 asrt( $beanA->equals( $beanB ), TRUE );
519                 asrt( $beanB->equals( $beanA ), TRUE );
520                 $beanB = R::dispense( 'carrot' );
521                 $beanB->id = $beanA->id;
522                 asrt( $beanA->equals( $beanB ), FALSE );
523                 asrt( $beanB->equals( $beanA ), FALSE );
524         }
525   
526         /**
527          * Test if adding SimpleModles to a shared list will auto unbox them.
528          */
529         public function testSharedListsAutoUnbox() {
530                 $boxedBean = R::dispense( 'boxedbean' );
531                 $bean = R::dispense( 'bean' );
532                 $model = new SimpleModel();
533                 $model->loadBean($boxedBean);
534                 $bean->ownBoxedbeanList[] = $model;
535                 try {
536                         R::store( $bean );
537                         pass();
538                 } catch ( \Exception $e ) {
539                         fail();
540                 }
541         }
542 }