Yaffs site version 1.1
[yaffs-website] / vendor / gabordemooij / redbean / testing / RedUNIT / Blackhole / Misc.php
1 <?php
2
3 namespace RedUNIT\Blackhole;
4
5 use RedUNIT\Blackhole as Blackhole;
6 use RedBeanPHP\Facade as R;
7 use RedBeanPHP\OODBBean as OODBBean;
8 use RedBeanPHP\Driver\RPDO as RPDO;
9 use RedBeanPHP\Logger\RDefault as RDefault;
10 use RedBeanPHP\RedException as RedException;
11 use RedBeanPHP\BeanHelper\SimpleFacadeBeanHelper as SimpleFacadeBeanHelper;
12 use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter;
13
14 /**
15  * Misc
16  *
17  * This test suite contains tests for a various functionalities
18  * and scenarios. For more details please consult the document
19  * section attached to each individual test method listed here.
20  *
21  * @file    RedUNIT/Blackhole/Misc.php
22  * @desc    Tests various features that do not rely on a database connection.
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
31 class Misc extends Blackhole
32 {
33         /*
34          * What drivers should be loaded for this test pack?
35          */
36         public function getTargetDrivers()
37         {
38                 return array( 'sqlite' );
39         }
40
41         /**
42          * Test whether we can use the JSONSerializable interface and
43          * whether old-style JSON is still the same (backwards compatibility).
44          *
45          * @return void
46          */
47         public function testJSONSerialize()
48         {
49                 $hotel = R::dispense( 'hotel' );
50                 $hotel->name = 'Overlook';
51                 $room = R::dispense( 'room' );
52                 $room->number = 237;
53                 $hotel->ownRoomList[] = $room;
54                 $shine = (string) $hotel;
55                 asrt( $shine, '{"id":0,"name":"Overlook"}' ); //basic JSON
56                 $shine = json_encode( $hotel->jsonSerialize() ); //As of PHP 5.4 json_encode() will call jsonSerializable
57                 asrt( $shine, '{"id":0,"name":"Overlook","ownRoom":[{"id":0,"number":237}]}' ); //should get full JSON
58         }
59
60         /**
61          * Tests max parameter binding.
62          *
63          * @return void
64          */
65         public function testIntegerBindingMax()
66         {
67                 if ( defined( 'HHVM_VERSION' ) ) return; //not for hhvm...
68                 $driver = new RPDO( 'test-sqlite-53', 'user', 'pass' );
69                 $max = $driver->getIntegerBindingMax();
70                 asrt( $max, 2147483647 );
71                 $driver = new RPDO( 'cubrid', 'user', 'pass' );
72                 $max = $driver->getIntegerBindingMax();
73                 asrt( $max, 2147483647 );
74                 $driver = new RPDO( 'other', 'user', 'pass' );
75                 $max = $driver->getIntegerBindingMax();
76                 asrt( $max, PHP_INT_MAX );
77         }
78
79         /**
80         * Should not be able to pass invalid mode (must be 0 or 1).
81         *
82         */
83         public function testInvalidDebugModeException()
84         {
85                 try {
86                         R::debug( TRUE, 6 );
87                         fail();
88                 } catch ( RedException $e ) {
89                         pass();
90                 }
91                 R::debug( FALSE );
92         }
93
94         /**
95          * Adding a database twice no longer allowed, causes confusion
96          * and possible damage.
97          */
98         public function testAddingTwice()
99         {
100                 testpack( 'Test adding DB twice.' );
101
102                 try {
103                         R::addDatabase( 'sqlite', '' );
104                         fail();
105                 } catch ( RedException $ex ) {
106                         pass();
107                 }
108         }
109
110         /**
111          * Tests whether getID never produces a notice.
112          *
113          * @return void
114          */
115         public function testGetIDShouldNeverPrintNotice()
116         {
117                 set_error_handler(function($err, $errStr){
118                         die('>>>>FAIL :'.$err.' '.$errStr);
119                 });
120                 $bean = new OODBBean;
121                 $bean->getID();
122                 restore_error_handler();
123                 pass();
124         }
125
126         /**
127          * Tests setProperty.
128          *
129          * @return void
130          */
131         public function testSetProperty()
132         {
133                 $bean = R::dispense( 'bean' );
134                 $bean->item = 2;
135                 $bean->ownBean = R::dispense( 'bean', 2 );
136                 R::store( $bean );
137                 $bean = $bean->fresh();
138                 $bean->ownBean;
139                 $bean->setProperty( 'ownBean', array(), FALSE, FALSE );
140                 asrt( count( $bean->ownBean ), 0 );
141                 asrt( count( $bean->getMeta( 'sys.shadow.ownBean' ) ), 2 );
142                 asrt( $bean->isTainted(), TRUE );
143                 $bean->setProperty( 'ownBean', array(), TRUE, FALSE );
144                 asrt( count( $bean->ownBean ), 0 );
145                 asrt( count( $bean->getMeta( 'sys.shadow.ownBean' ) ), 0 );
146                 asrt( $bean->isTainted(), TRUE );
147                 $bean = $bean->fresh();
148                 $bean->setProperty( 'ownBean', array(), TRUE, FALSE );
149                 asrt( count( $bean->ownBean ), 0 );
150                 asrt( count( $bean->getMeta( 'sys.shadow.ownBean' ) ), 0 );
151                 asrt( $bean->isTainted(), FALSE );
152                 $bean = $bean->fresh();
153                 $bean->setProperty( 'ownBean', array(), TRUE, TRUE );
154                 asrt( count( $bean->ownBean ), 0 );
155                 asrt( count( $bean->getMeta( 'sys.shadow.ownBean' ) ), 0 );
156                 asrt( $bean->isTainted(), TRUE );
157         }
158
159         /**
160          * Tests beansToArray().
161          *
162          * @return void
163          */
164         public function testBeansToArray()
165         {
166                 testpack('Test R::beansToArray method');
167                 $bean1 = R::dispense( 'bean' );
168                 $bean1->name = 'hello';
169                 $bean2 = R::dispense( 'bean' );
170                 $bean2->name = 'world';
171                 $beans = array( $bean1, $bean2 );
172                 $array = R::beansToArray( $beans );
173                 asrt( $array[0]['name'], 'hello' );
174                 asrt( $array[1]['name'], 'world' );
175         }
176
177         /**
178          * Test debugging with custom logger.
179          *
180          * @return void
181          */
182         public function testDebugCustomLogger()
183         {
184                 testpack( 'Test debug mode with custom logger' );
185                 $pdoDriver = new RPDO( R::getDatabaseAdapter()->getDatabase()->getPDO() );
186                 $customLogger = new CustomLogger;
187                 $pdoDriver->setDebugMode( TRUE, $customLogger );
188                 $pdoDriver->Execute( 'SELECT 123' );
189                 asrt( count( $customLogger->getLogMessage() ), 1 );
190                 $pdoDriver->setDebugMode( TRUE, NULL );
191                 asrt( ( $pdoDriver->getLogger() instanceof RDefault ), TRUE );
192                 testpack( 'Test bean->getProperties method' );
193                 $bean = R::dispense( 'bean' );
194                 $bean->property = 'hello';
195                 $props = $bean->getProperties();
196                 asrt( isset( $props['property'] ), TRUE );
197                 asrt( $props['property'], 'hello' );
198
199         }
200
201         /**
202          * Test Facade transactions.
203          *
204          * @return void
205          *
206          * @throws\Exception
207          */
208         public function testTransactionInFacade()
209         {
210                 testpack( 'Test transaction in facade' );
211                 $bean = R::dispense( 'bean' );
212                 $bean->name = 'a';
213                 R::store( $bean );
214                 R::trash( $bean );
215                 R::freeze( TRUE );
216                 $bean = R::dispense( 'bean' );
217                 $bean->name = 'a';
218                 R::store( $bean );
219                 asrt( R::count( 'bean' ), 1 );
220                 R::trash( $bean );
221                 asrt( R::count( 'bean' ), 0 );
222                 $bean = R::dispense( 'bean' );
223                 $bean->name = 'a';
224                 $id = R::transaction( function() use( &$bean ) {
225                         return R::transaction( function() use( &$bean ) {
226                                 return R::store( $bean );
227                         } );
228                 } );
229                 asrt( (int) $id, (int) $bean->id );
230                 R::trash( $bean );
231                 $bean = R::dispense( 'bean' );
232                 $bean->name = 'a';
233                 $id = R::transaction( function() use( &$bean ) {
234                         return R::store( $bean );
235                 } );
236                 asrt( (int) $id, (int) $bean->id );
237                 R::trash( $bean );
238                 $bean = R::dispense( 'bean' );
239                 $bean->name = 'a';
240                 try {
241                         R::transaction( function () use ( $bean ) {
242                                 R::store( $bean );
243                                 R::transaction( function () {
244                                         throw new\Exception();
245                                 } );
246                         } );
247                 } catch (\Exception $e ) {
248                         pass();
249                 }
250                 asrt( R::count( 'bean' ), 0 );
251                 $bean = R::dispense( 'bean' );
252                 $bean->name = 'a';
253                 try {
254                         R::transaction( function () use ( $bean ) {
255                                 R::transaction( function () use ( $bean ) {
256                                         R::store( $bean );
257                                         throw new\Exception();
258                                 } );
259                         } );
260                 } catch (\Exception $e ) {
261                         pass();
262                 }
263                 asrt( R::count( 'bean' ), 0 );
264                 $bean = R::dispense( 'bean' );
265                 $bean->name = 'a';
266                 try {
267                         R::transaction( function () use ( $bean ) {
268                                 R::transaction( function () use ( $bean ) {
269                                         R::store( $bean );
270                                 } );
271                         } );
272                 } catch (\Exception $e ) {
273                         pass();
274                 }
275                 asrt( R::count( 'bean' ), 1 );
276                 R::freeze( FALSE );
277                 try {
278                         R::transaction( 'nope' );
279                         fail();
280                 } catch (\Exception $e ) {
281                         pass();
282                 }
283                 testpack( 'Test Camelcase 2 underscore' );
284                 $names = array(
285                         'oneACLRoute'              => 'one_acl_route',
286                         'ALLUPPERCASE'             => 'alluppercase',
287                         'clientServerArchitecture' => 'client_server_architecture',
288                         'camelCase'                => 'camel_case',
289                         'peer2peer'                => 'peer2peer',
290                         'fromUs4You'               => 'from_us4_you',
291                         'lowercase'                => 'lowercase',
292                         'a1A2b'                    => 'a1a2b',
293                 );
294                 $bean = R::dispense( 'bean' );
295                 foreach ( $names as $name => $becomes ) {
296                         $bean->$name = 1;
297                         asrt( isset( $bean->$becomes ), TRUE );
298                 }
299                 testpack( 'Misc Tests' );
300                 R::debug( 1 );
301                 flush();
302                 ob_start();
303                 R::exec( 'SELECT 123' );
304                 $out = ob_get_contents();
305                 ob_end_clean();
306                 flush();
307                 pass();
308                 asrt( ( strpos( $out, 'SELECT 123' ) !== FALSE ), TRUE );
309                 R::debug( 0 );
310                 flush();
311                 ob_start();
312                 R::exec( 'SELECT 123' );
313                 $out = ob_get_contents();
314                 ob_end_clean();
315                 flush();
316                 pass();
317                 asrt( $out, '' );
318                 R::debug( 0 );
319                 pass();
320                 testpack( 'test to string override' );
321                 $band = R::dispense( 'band' );
322                 $str = strval( $band );
323                 asrt( $str, 'bigband' );
324                 testpack( 'test whether we can use isset/set in model' );
325                 $band->setProperty( 'property1', 123 );
326                 asrt( $band->property1, 123 );
327                 asrt( $band->checkProperty( 'property1' ), TRUE );
328                 asrt( $band->checkProperty( 'property2' ), FALSE );
329                 $band = new \Model_Band;
330                 $bean = R::dispense( 'band' );
331                 $bean->property3 = 123;
332                 $band->loadBean( $bean );
333                 $bean->property4 = 345;
334                 $band->setProperty( 'property1', 123 );
335                 asrt( $band->property1, 123 );
336                 asrt( $band->checkProperty( 'property1' ), TRUE );
337                 asrt( $band->checkProperty( 'property2' ), FALSE );
338                 asrt( $band->property3, 123 );
339                 asrt( $band->property4, 345 );
340                 testpack( 'Can we pass a\PDO object to Setup?' );
341                 $pdo = new \PDO( 'sqlite:test.db' );
342                 R::addDatabase( 'pdo', $pdo );
343                 R::selectDatabase( 'pdo' );
344                 R::getCell('SELECT 123;');
345                 testpack( 'Test array interface of beans' );
346                 $bean = R::dispense( 'bean' );
347                 $bean->hello = 'hi';
348                 $bean->world = 'planet';
349                 asrt( $bean['hello'], 'hi' );
350                 asrt( isset( $bean['hello'] ), TRUE );
351                 asrt( isset( $bean['bye'] ), FALSE );
352                 $bean['world'] = 'sphere';
353                 asrt( $bean->world, 'sphere' );
354                 foreach ( $bean as $key => $el ) {
355                         if ( $el == 'sphere' || $el == 'hi' || $el == 0 ) {
356                                 pass();
357                         } else {
358                                 fail();
359                         }
360                         if ( $key == 'hello' || $key == 'world' || $key == 'id' ) {
361                                 pass();
362                         } else {
363                                 fail();
364                         }
365                 }
366                 asrt( count( $bean ), 3 );
367                 unset( $bean['hello'] );
368                 asrt( count( $bean ), 2 );
369                 asrt( count( R::dispense( 'countable' ) ), 1 );
370                 // Otherwise untestable...
371                 $bean->setBeanHelper( new SimpleFacadeBeanHelper() );
372                 R::getRedBean()->setBeanHelper( new SimpleFacadeBeanHelper() );
373                 pass();
374                 // Test whether properties like owner and shareditem are still possible
375                 testpack( 'Test Bean Interface for Lists' );
376                 $bean = R::dispense( 'bean' );
377                 // Must not be list, because first char after own is lowercase
378                 asrt( is_array( $bean->owner ), FALSE );
379                 // Must not be list, because first char after shared is lowercase
380                 asrt( is_array( $bean->shareditem ), FALSE );
381                 asrt( is_array( $bean->own ), FALSE );
382                 asrt( is_array( $bean->shared ), FALSE );
383                 asrt( is_array( $bean->own_item ), FALSE );
384                 asrt( is_array( $bean->shared_item ), FALSE );
385                 asrt( is_array( $bean->{'own item'} ), FALSE );
386                 asrt( is_array( $bean->{'shared Item'} ), FALSE );
387         }
388
389         public function testConv2Beans()
390         {
391                 $row1 = array('id' => 1, 'title'=>'test');
392                 $row2 = array('id' => 2, 'title'=>'test2');
393                 $beans = R::convertToBeans('page', array($row1, $row2));
394                 asrt(count($beans), 2);
395                 asrt($beans[2]->title, 'test2');
396         }
397
398         /**
399         * Test the most important invalid bean combinations.
400         *
401         * @return void
402         */
403         public function testInvalidType()
404         {
405                 $invalid = array(
406                         'book_page', //no link beans
407                         'a_b_c', //no prefix
408                         'a b', //no space
409                         'bean@', //no invalid symbols
410                         'bean#', //no invalid symbols
411                         'bean$', //sometimes used in DB, not allowed
412                         '__bean',//no prefixes
413                         '.bean', //no object notation
414                         'bean-item', //no dash
415                         'beanOther'); //no camelcase (uppercase because of file system issues)
416
417                 foreach( $invalid as $j ) {
418                         try {
419                                 R::dispense( $j );
420                                 fail();
421                         } catch( RedException $e ) {
422                                 pass();
423                         }
424                 }
425         }
426
427         /**
428         * Test whether batch still works if no IDs have been passed.
429         *
430         * @return void
431         */
432         public function testBatch0()
433         {
434                 $zero = R::batch( 'page', array() );
435                 asrt( is_array( $zero ), TRUE );
436                 asrt( count( $zero ), 0 );
437                 $zero = R::batch( 'page', FALSE );
438                 asrt( is_array( $zero ), TRUE );
439                 asrt( count( $zero ), 0 );
440                 $zero = R::batch( 'page', NULL);
441                 asrt( is_array( $zero ), TRUE );
442                 asrt( count( $zero ), 0 );
443         }
444
445         /**
446         * Test whether connection failure does not reveal
447         * credentials.
448         *
449         * @return void
450         */
451         public function testConnect()
452         {
453                 $driver = new RPDO( 'dsn:invalid', 'usr', 'psst' );
454                 try {
455                         $driver->connect();
456                         fail();
457                 }
458                 catch( \PDOException $e ) {
459                         asrt( strpos( $e->getMessage(), 'invalid' ), FALSE );
460                         asrt( strpos( $e->getMessage(), 'usr' ), FALSE );
461                         asrt( strpos( $e->getMessage(), 'psst' ), FALSE );
462                 }
463         }
464
465         /**
466         * Test whether we can create an instant database using
467         * R::setup().
468         *
469         * Probably only works on *NIX systems.
470         *
471         * @return void
472         */
473         public function testSetup()
474         {
475                 $tmpDir = sys_get_temp_dir();
476                 R::setup();
477         }
478
479         /**
480          * Test camelCase to snake_case conversions.
481          *
482          * @return void
483          */
484         public function testCamel2Snake()
485         {
486                 asrt( AQueryWriter::camelsSnake('bookPage'), 'book_page' );
487                 asrt( AQueryWriter::camelsSnake('FTP'), 'ftp' );
488                 asrt( AQueryWriter::camelsSnake('ACLRules'), 'acl_rules' );
489                 asrt( AQueryWriter::camelsSnake('SSHConnectionProxy'), 'ssh_connection_proxy' );
490                 asrt( AQueryWriter::camelsSnake('proxyServerFacade'), 'proxy_server_facade' );
491                 asrt( AQueryWriter::camelsSnake('proxySSHClient'), 'proxy_ssh_client' );
492                 asrt( AQueryWriter::camelsSnake('objectACL2Factory'), 'object_acl2_factory' );
493                 asrt( AQueryWriter::camelsSnake('bookItems4Page'), 'book_items4_page' );
494                 asrt( AQueryWriter::camelsSnake('book☀Items4Page'), 'book☀_items4_page' );
495         }
496 }
497
498 /**
499  * Custom Logger class.
500  * For testing purposes.
501  */
502 class CustomLogger extends RDefault
503 {
504
505         private $log;
506
507         public function getLogMessage()
508         {
509                 return $this->log;
510         }
511
512         public function log()
513         {
514                 $this->log = func_get_args();
515         }
516 }