PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/testing/helpers/functions.php

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