Yaffs site version 1.1
[yaffs-website] / vendor / gabordemooij / redbean / testing / helpers / functions.php
1 <?php
2
3 /**
4  * Convenience function for test hook.
5  * If you added the proper Writer class, the facade should be able
6  * to automatically load it, i.e. \RedBeanPHP\QueryWriter\MyWriter
7  *
8  * @global array $ini
9  *
10  * @param string $name name of the connection (key)
11  * @param string $dsn  DSN to connect
12  * @param string $user username
13  * @param string $pass passwords
14  */
15 function add_writer_to_tests( $name, $dsn, $user, $pass )
16 {
17
18         global $ini;
19
20         \RedUNIT\Base::addToDriverList( $name );
21         R::addDatabase( $name, $dsn, $user, $pass );
22
23         $ini[ $name ] = true;
24 }
25
26 /**
27  * A simple print function that works
28  * both for CLI and HTML.
29  *
30  * @param string $text
31  */
32 function printtext( $text )
33 {
34         if ( $_SERVER["DOCUMENT_ROOT"] ) {
35                 echo "<BR>" . $text;
36         } else {
37                 echo "\n" . $text;
38         }
39 }
40
41 /**
42  * Tests whether a === b. The minimalistic core of this little
43  * unit test framework.
44  *
45  * @global integer $tests
46  *
47  * @param mixed    $a value for A
48  * @param mixed    $b value for B
49  */
50 function asrt( $a, $b )
51 {
52         if ( $a === $b ) {
53                 global $tests;
54
55                 $tests++;
56
57                 print( "[" . $tests . "]" );
58         } else {
59                 printtext( "FAILED TEST: EXPECTED $b BUT GOT: $a " );
60
61                 fail();
62         }
63 }
64
65 /**
66  * called when a test is passed. prints the test number to the screen.
67  */
68 function pass()
69 {
70         global $tests;
71
72         $tests++;
73
74         print( "[" . $tests . "]" );
75 }
76
77 /**
78  * called when a test fails. shows debug info and exits.
79  */
80 function fail()
81 {
82         printtext( "FAILED TEST" );
83
84         debug_print_backtrace();
85
86         exit( 1 );
87 }
88
89 /**
90  * prints out the name of the current test pack.
91  *
92  * @param string $name name of the test pack
93  */
94 function testpack( $name )
95 {
96         printtext( "\n\tSub testpack: " . $name . " \n\t" );
97 }
98
99 /**
100  * prints out the name of the current test pack.
101  *
102  * @param string $name name of the test pack
103  */
104 function maintestpack( $name )
105 {
106         printtext( "\n\nTestpack: " . $name . " \n\t" );
107 }
108
109 /**
110  * Quickly resolves the formatted table name
111  */
112 function tbl( $table )
113 {
114         return R::$writer->getFormattedTableName( $table );
115 }
116
117 /**
118  * Quickly resolves the formatted ID
119  */
120 function ID( $table )
121 {
122         return R::$writer->getIDField( $table );
123 }
124
125 /**
126  * Emulates legacy function for use with older tests.
127  */
128 function set1toNAssoc( $a, \RedBeanPHP\OODBBean $bean1, \RedBeanPHP\OODBBean $bean2 )
129 {
130         $type = $bean1->getMeta( "type" );
131
132         $a->clearRelations( $bean2, $type );
133         $a->associate( $bean1, $bean2 );
134
135         if ( count( $a->related( $bean2, $type ) ) === 1 ) {
136                 // return $this;
137         } else {
138                 throw new \RedBeanPHP\RedException\SQL( "Failed to enforce 1-N Relation for $type " );
139         }
140 }
141
142 /**
143  * Returns all property values of beans as a
144  * comma separated string sorted.
145  *
146  * @param array  $beans    beans
147  * @param string $property name of the property
148  *
149  * @return string $values  values
150  */
151 function getList( $beans, $property )
152 {
153         $items = array();
154
155         foreach ( $beans as $bean ) {
156                 $items[] = $bean->$property;
157         }
158
159         sort( $items );
160
161         return implode( ",", $items );
162 }
163
164 /**
165  * Helper function to test IDs
166  *
167  * @param array $array array
168  */
169 function testids( $array )
170 {
171         foreach ( $array as $key => $bean ) {
172                 asrt( intval( $key ), intval( $bean->getID() ) );
173         }
174 }
175
176 /**
177  * Group modifier function. Tests random modifications
178  * of groups of beans. For use with tests that test N:1 relation mapping
179  * features.
180  *
181  * @param mixed $book3    book
182  * @param mixed $quotes   quotes
183  * @param mixed $pictures pictures
184  * @param mixed $topics   topics
185  */
186 function modgr( $book3, $quotes, $pictures, $topics )
187 {
188         $key = array_rand( $quotes );
189
190         $quote = $quotes[$key];
191
192         $keyPic = array_rand( $pictures );
193
194         $picture = $pictures[$keyPic];
195
196         $keyTop = array_rand( $topics );
197
198         $topic = $topics[$keyTop];
199
200         if ( rand( 0, 1 ) ) {
201                 $f = 0;
202
203                 foreach ( $book3->ownQuote as $z ) {
204                         if ( $z->note == $quote->note ) {
205                                 $f = 1;
206
207                                 break;
208                         }
209                 }
210                 if ( !$f ) {
211                         //echo "\n add a quote ";
212
213                         $book3->ownQuote[] = $quote;
214                 }
215         }
216
217         if ( rand( 0, 1 ) ) {
218                 $f = 0;
219
220                 foreach ( $book3->ownPicture as $z ) {
221                         if ( $z->note == $picture->note ) {
222                                 $f = 1;
223
224                                 break;
225                         }
226                 }
227                 if ( !$f ) {
228                         //      echo "\n add a picture ";
229
230                         $book3->ownPicture[] = $picture;
231                 }
232         }
233
234         if ( rand( 0, 1 ) ) {
235                 $f = 0;
236
237                 foreach ( $book3->sharedTopic as $z ) {
238                         if ( $z->note == $topic->note ) {
239                                 $f = 1;
240
241                                 break;
242                         }
243                 }
244
245                 if ( !$f ) {
246                         $book3->sharedTopic[] = $topic;
247                 }
248         }
249
250         if ( rand( 0, 1 ) && count( $book3->ownQuote ) > 0 ) {
251                 $key = array_rand( $book3->ownQuote );
252
253                 unset( $book3->ownQuote[$key] );
254         }
255
256         if ( rand( 0, 1 ) && count( $book3->ownPicture ) > 0 ) {
257                 $key = array_rand( $book3->ownPicture );
258
259                 unset( $book3->ownPicture[$key] );
260         }
261
262         if ( rand( 0, 1 ) && count( $book3->sharedTopic ) > 0 ) {
263                 $key = array_rand( $book3->sharedTopic );
264
265                 unset( $book3->sharedTopic[$key] );
266         }
267
268         if ( rand( 0, 1 ) && count( $book3->ownPicture ) > 0 ) {
269                 $key = array_rand( $book3->ownPicture );
270
271                 $book3->ownPicture[$key]->change = rand( 0, 100 );
272         }
273
274         if ( rand( 0, 1 ) && count( $book3->ownQuote ) > 0 ) {
275                 $key = array_rand( $book3->ownQuote );
276
277                 $book3->ownQuote[$key]->change = 'note ch ' . rand( 0, 100 );
278         }
279
280         if ( rand( 0, 1 ) && count( $book3->sharedTopic ) > 0 ) {
281                 $key = array_rand( $book3->sharedTopic );
282
283                 $book3->sharedTopic[$key]->change = rand( 0, 100 );
284         }
285 }
286
287 /**
288  * SetGet function, sets a value in a bean and retrieves it again
289  * after storage, useful for tests that want to make sure the same value
290  * that gets in, comes out again.
291  *
292  * @param mixed $val the value that needs to be preserved
293  *
294  * @return mixed $val the value as returned after storage-retrieval cycle.
295  */
296 function setget( $val )
297 {
298         R::nuke();
299
300         $bean = R::dispense( "page" );
301
302         $bean->prop = $val;
303
304         $id = R::store( $bean );
305
306         $bean = R::load( "page", $id );
307
308         return $bean->prop;
309 }
310
311 /**
312  * Wrapper function to test BeanCan Server, does the boring
313  * plumming work.
314  *
315  * @param mixed  $data   Data for JSON-RPC request object
316  * @param mixed  $params Parameters for JSON-RPC request object
317  * @param string $id     Identification of JSON-RPC request to connect to response
318  *
319  * @return string $out Output JSON from BeanCan server.
320  */
321 function fakeBeanCanServerRequest( $data, $params = NULL, $id = "1234", $whiteList = 'all' )
322 {
323         $j = array(
324                 "jsonrpc" => "2.0",
325                 "method"  => $data,
326                 "params"  => $params,
327                 "id"      => $id
328         );
329
330         $can = new \RedBeanPHP\Plugin\BeanCan;
331
332         $request = json_encode( $j );
333
334         $can->setWhitelist( $whiteList );
335
336         $out = $can->handleJSONRequest( $request );
337
338         return $out;
339 }
340
341 /**
342  * Candy Cane Factory. Produces lots of candy canes.
343  *
344  * @return array $canes canes
345  */
346 function candy_canes()
347 {
348         $canes = R::dispense( 'cane', 10 );
349
350         $i = 0;
351
352         foreach ( $canes as $k => $cane ) {
353                 $canes[$k]->label = 'Cane No. ' . ( $i++ );
354         }
355
356         $canes[0]->cane = $canes[1];
357         $canes[1]->cane = $canes[4];
358         $canes[9]->cane = $canes[4];
359         $canes[6]->cane = $canes[4];
360         $canes[4]->cane = $canes[7];
361         $canes[8]->cane = $canes[7];
362
363         return $canes;
364 }
365
366 /**
367  * Returns an array containing the index names of all
368  * indexes on the specified table name.
369  *
370  * @param $tableNoQ table name without quotes or backticks
371  *
372  * @return array
373  */
374 function getIndexes( $tableNoQ )
375 {
376         $writer = R::getWriter();
377
378         if ( ( $writer instanceof \RedBeanPHP\QueryWriter\MySQL ) || ( $writer instanceof \RedBeanPHP\QueryWriter\CUBRID ) ) {
379                 $indexes = array();
380                 $list = R::getAll( "SHOW INDEX FROM `{$tableNoQ}`" );
381                 foreach( $list as $listItem ) {
382                         $indexes[] = $listItem['Key_name'];
383                 }
384                 return $indexes;
385         }
386
387         if ( ( $writer instanceof \RedBeanPHP\QueryWriter\SQLiteT ) ) {
388                 $indexes = array();
389                 $list = R::getAll( " pragma index_list(`{$tableNoQ}`) " );
390                 foreach( $list as $listItem ) {
391                         $indexes[] = $listItem['name'];
392                 }
393                 return $indexes;
394         }
395
396         if ( ( $writer instanceof \RedBeanPHP\QueryWriter\PostgreSQL ) ) {
397                 return R::getCol( " SELECT indexname FROM pg_indexes WHERE tablename = '{$tableNoQ}' AND schemaname = 'public' " );
398         }
399
400         return array();
401 }
402
403 function are_cols_in_unique( $type, $properties )
404 {
405         sort( $properties );
406         $propertyFootprint = implode( ',', $properties );
407         $uniques = get_uniques_for_type( $type );
408         foreach( $uniques as $unique ) {
409                 sort( $unique );
410                 $uniqueFootprint = implode( ',', $unique );
411                 if ( $uniqueFootprint === $propertyFootprint ) return TRUE;
412         }
413         return FALSE;
414 }
415
416 function get_uniques_for_type( $type )
417 {
418         $list = array();
419         $writer = R::getWriter();
420         $adapter = R::getDatabaseAdapter();
421         global $currentDriver;
422         switch( $currentDriver ) {
423                 case 'mysql':
424                         $table = $writer->esc( $type, TRUE );
425                         $columns = $adapter->get('
426                                 SELECT
427                                 information_schema.key_column_usage.constraint_name,
428                                 information_schema.key_column_usage.column_name
429                                 FROM
430                                 information_schema.table_constraints
431                                 INNER JOIN information_schema.key_column_usage
432                                 ON (
433                                 information_schema.table_constraints.constraint_name = information_schema.key_column_usage.constraint_name
434                                 AND information_schema.table_constraints.constraint_schema = information_schema.key_column_usage.constraint_schema
435                                 AND information_schema.table_constraints.constraint_catalog = information_schema.key_column_usage.constraint_catalog
436                                 )
437                                 WHERE
438                                 information_schema.table_constraints.table_schema IN (SELECT DATABASE())
439                                 AND information_schema.table_constraints.table_name = ?
440                                 AND information_schema.table_constraints.constraint_type = \'UNIQUE\'
441                         ', array( $table ) );
442                         $uniques = array();
443                         foreach( $columns as $column ) {
444                                 if ( !isset( $uniques[ $column['constraint_name'] ] ) ) $uniques[ $column['constraint_name'] ] = array();
445                                 $uniques[ $column['constraint_name'] ][] = $column['column_name'];
446                         }
447                         $list = $uniques;
448                 break;
449                 case 'pgsql':
450                         $table = $writer->esc( $type, TRUE );
451                         $columns = $adapter->get('
452                                 SELECT
453                                 information_schema.key_column_usage.constraint_name,
454                                 information_schema.key_column_usage.column_name
455                                 FROM
456                                 information_schema.table_constraints
457                                 INNER JOIN information_schema.key_column_usage
458                                 ON (
459                                 information_schema.table_constraints.constraint_name = information_schema.key_column_usage.constraint_name
460                                 AND information_schema.table_constraints.constraint_schema = information_schema.key_column_usage.constraint_schema
461                                 AND information_schema.table_constraints.constraint_catalog = information_schema.key_column_usage.constraint_catalog
462                                 )
463                                 WHERE
464                                 information_schema.table_constraints.table_catalog = current_database()
465                                 AND information_schema.key_column_usage.table_schema = ANY( current_schemas( FALSE ) )
466                                 AND information_schema.table_constraints.table_name = ?
467                                 AND information_schema.table_constraints.constraint_type = \'UNIQUE\'
468                                 ', array( $table ) );
469                         $uniques = array();
470                         foreach( $columns as $column ) {
471                                 if ( !isset( $uniques[ $column['constraint_name'] ] ) ) $uniques[ $column['constraint_name'] ] = array();
472                                 $uniques[ $column['constraint_name'] ][] = $column['column_name'];
473                         }
474                         $list= $uniques;
475                 break;
476                 case 'sqlite':
477                         $uniques = array();
478                         $table = $writer->esc( $type, TRUE );
479                         $indexes = $adapter->get( "PRAGMA index_list({$table})" );
480                         foreach( $indexes as $index ) {
481                                 if ( $index['unique'] == 1 ) {
482                                         $info = $adapter->get( "PRAGMA index_info({$index['name']})" );
483                                         if ( !isset( $uniques[$index['name']] ) ) $uniques[$index['name']] = array();
484                                         foreach( $info as $piece ) {
485                                                 $uniques[$index['name']][] = $piece['name'];
486                                         }
487                                 }
488                         }
489                         $list = $uniques;
490                 break;
491                 case 'CUBRID':
492                         try {
493                                 $sqlCode = $adapter->get("SHOW CREATE TABLE `{$type}`");
494                         } catch ( \Exception $e ) {
495                                 $sqlCode = '';
496                         }
497                         if (!isset($sqlCode[0])) return array();
498                         $matches = array();
499                         preg_match_all('/CONSTRAINT\s+\[([\w_]+)\]\s+UNIQUE\s+KEY\s+\(([^\)]+)\)/', $sqlCode[0]['CREATE TABLE'], $matches);
500                         $list = array();
501                         if (!isset($matches[0])) return $list;
502                         $max = count($matches[0]);
503                         for($i = 0; $i < $max; $i++) {
504                                 $columns = explode(',', $matches[2][$i]);
505                                 foreach( $columns as $key => $column ) {
506                                         $columns[$key] = trim( $column, '[] ');
507                                 }
508                                 $list[ $matches[1][$i] ] = $columns;
509                         }
510                 break;
511         }
512         return $list;
513 }