PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/Test/Case.php

https://github.com/toshibr/hashmark
PHP | 426 lines | 190 code | 57 blank | 179 comment | 26 complexity | 36876459b8b71c4199e3f8ae715e55b0 MD5 | raw file
  1. <?php
  2. // vim: fenc=utf-8:ft=php:ai:si:ts=4:sw=4:et:
  3. /**
  4. * Hashmark_TestCase
  5. *
  6. * @filesource
  7. * @link http://code.google.com/p/hashmark/
  8. * @link http://framework.zend.com/manual/en/coding-standard.html
  9. * @link http://phpdoc.org/tutorial.php
  10. * @copyright Copyright (c) 2008-2009, Code Actual LLC
  11. * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  12. * @package Hashmark-Test
  13. * @subpackage Base
  14. * @version $Id: Case.php 294 2009-02-13 03:48:59Z david $
  15. */
  16. /**
  17. * Base class for all module test classes.
  18. *
  19. * @abstract
  20. * @package Hashmark-Test
  21. * @subpackage Base
  22. */
  23. abstract class Hashmark_TestCase extends PHPUnit_Framework_TestCase
  24. {
  25. /**
  26. * @access protected
  27. * @var boolean If true, PHPUnit lets globals persist between tests.
  28. * @link http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html
  29. */
  30. protected $backupGlobals = false;
  31. /**
  32. * @access protected
  33. * @var mixed Database connection object/resource.
  34. * @see setUp()
  35. */
  36. protected $_db;
  37. /**
  38. * @access protected
  39. * @var Hashmark_DbHelper_* Instance created in setUp().
  40. */
  41. protected $_dbHelper;
  42. /**
  43. * @access protected
  44. * @var string Test case type, ex. 'Mysql'.
  45. * @see setUp()
  46. */
  47. protected $_type;
  48. /**
  49. * Set up the test case fixtures.
  50. *
  51. * @access protected
  52. * @return void
  53. */
  54. protected function setUp()
  55. {
  56. // Extract suffix (ex. 'Mysql') from class (ex. 'Hashmark_TestCase_Client_Mysql').
  57. $className = get_class($this);
  58. $this->_type = substr($className, strrpos($className, '_') + 1);
  59. // Auto-load a DbHelper instance for DB dependent modules.
  60. $matchingDbHelperFile = dirname(__FILE__) . '/../DbHelper/' . HASHMARK_DBHELPER_DEFAULT_TYPE . '.php';
  61. if (is_readable($matchingDbHelperFile)) {
  62. $this->_dbHelper = Hashmark::getModule('DbHelper', HASHMARK_DBHELPER_DEFAULT_TYPE);
  63. $this->_db = $this->_dbHelper->openDb('unittest');
  64. }
  65. }
  66. /**
  67. * @access protected
  68. * @return void
  69. */
  70. protected function tearDown()
  71. {
  72. if ($this->_dbHelper) {
  73. $this->_dbHelper->closeDb($this->_db);
  74. }
  75. }
  76. /**
  77. * Return a @dataProvider-compat argument set without the array()
  78. * wrapping around each value.
  79. *
  80. * @static
  81. * @access public
  82. * @return Array
  83. */
  84. public static function unwrapProviderData($providerData)
  85. {
  86. array_walk($providerData, create_function('&$v,$k', '$v = $v[0];'));
  87. return $providerData;
  88. }
  89. /**
  90. * Provide valid increment values (initial, delta, expected result).
  91. *
  92. * @static
  93. * @access public
  94. * @return Array Test method argument sets.
  95. * @see Loaded data file for return value format.
  96. */
  97. public static function provideIncrementValues()
  98. {
  99. static $data;
  100. require_once dirname(__FILE__) . '/Core/Data/' . __FUNCTION__ . '.php';
  101. return $data;
  102. }
  103. /**
  104. * Provide valid decrement values (initial, delta, expected result).
  105. *
  106. * @static
  107. * @access public
  108. * @return Array Test method argument sets.
  109. * @see Loaded data file for return value format.
  110. */
  111. public static function provideDecrementValues()
  112. {
  113. static $data;
  114. require_once dirname(__FILE__) . '/Core/Data/' . __FUNCTION__ . '.php';
  115. return $data;
  116. }
  117. /**
  118. * Provide valid string values.
  119. *
  120. * @static
  121. * @access public
  122. * @return Array Test method argument sets.
  123. */
  124. public static function provideStringValues()
  125. {
  126. static $data;
  127. if (!$data) {
  128. $data = array(array(''),
  129. array(' '),
  130. array('87a46c25bc0723ada70db470198e887d'));
  131. }
  132. return $data;
  133. }
  134. /**
  135. * Provide valid decimal values.
  136. *
  137. * @static
  138. * @access public
  139. * @return Array Test method argument sets.
  140. */
  141. public static function provideDecimalValues()
  142. {
  143. static $data;
  144. if (!$data) {
  145. $data = array(array('0'),
  146. array('1'),
  147. array('-1'),
  148. array('1.0001'),
  149. array('-1.0001'),
  150. array('0.0001'),
  151. array('-0.0001'),
  152. array('1000000000000000.0001'),
  153. array('-1000000000000000.0001'));
  154. }
  155. return $data;
  156. }
  157. /**
  158. * Provide names which should never identify a scalar.
  159. *
  160. * @static
  161. * @access public
  162. * @return Array Test method argument sets.
  163. */
  164. public static function provideInvalidScalarNames()
  165. {
  166. static $data;
  167. if (!$data) {
  168. $data = array(array(''),
  169. array(' '),
  170. array(null),
  171. array(true),
  172. array(false),
  173. array(0),
  174. array(1),
  175. array(-1));
  176. }
  177. return $data;
  178. }
  179. /**
  180. * Provide sets of scalar types and values.
  181. *
  182. * @static
  183. * @access public
  184. * @return Array Test method argument sets.
  185. *
  186. * Format:
  187. *
  188. * array(array('decimal', 0),
  189. * ...
  190. * array('string', 'aef448733247db5be49ae8597aa94d59S'));
  191. */
  192. public static function provideScalarTypesAndValues()
  193. {
  194. static $data;
  195. if (!$data) {
  196. $strings = self::provideStringValues();
  197. $numbers = self::provideDecimalValues();
  198. $data = array();
  199. foreach ($strings as $str) {
  200. $data[] = array('string', $str[0]);
  201. }
  202. foreach ($numbers as $num) {
  203. $data[] = array('decimal', $num[0]);
  204. }
  205. }
  206. return $data;
  207. }
  208. /**
  209. * Provide fields of scalars scheduled for sampling.
  210. *
  211. * @static
  212. * @access public
  213. * @return Array Test method argument sets.
  214. */
  215. public static function provideScalarsWithScheduledSamplers()
  216. {
  217. static $data;
  218. if (!$data) {
  219. foreach (Hashmark_Core::getValidScalarTypes() as $type) {
  220. $argSet = array();
  221. $argSet['name'] = self::randomString();
  222. $argSet['type'] = $type;
  223. $argSet['description'] = self::randomString();
  224. $argSet['sampler_status'] = 'Scheduled';
  225. $argSet['sampler_handler'] = 'Test';
  226. $argSet['sampler_start'] = gmdate(HASHMARK_DATETIME_FORMAT);
  227. // 0-minute frequencies will make them due to run immediately.
  228. $argSet['sampler_frequency'] = 0;
  229. $data[] = $argSet;
  230. }
  231. }
  232. return $data;
  233. }
  234. /**
  235. * Return a random decimal string.
  236. *
  237. * @static
  238. * @access public
  239. * @return string
  240. */
  241. public static function randomDecimal()
  242. {
  243. // Random DECIMAL(M,D) numbers.
  244. // @see DECIMAL type, http://dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html#id4944739
  245. // Before decimal point:
  246. $value = '';
  247. $wholeDigits = mt_rand(1, HASHMARK_DECIMAL_TOTALWIDTH - HASHMARK_DECIMAL_RIGHTWIDTH);
  248. for ($d = 0; $d < $wholeDigits; $d++) {
  249. $value .= mt_rand(0, 9);
  250. }
  251. // After:
  252. $value = preg_replace('/^0+/', '', $value) . '.';
  253. $pointDigits = mt_rand(1, HASHMARK_DECIMAL_RIGHTWIDTH);
  254. for ($d = 0; $d < $pointDigits; $d++) {
  255. $value .= mt_rand(0, 9);
  256. }
  257. return $value;
  258. }
  259. /**
  260. * Return a random string.
  261. *
  262. * @static
  263. * @access public
  264. * @param int $minLength 1 to 40.
  265. * @param int $maxLength 1 to 40.
  266. * @return string
  267. * @throws Exception If $minLength or $maxLength is greater than 40 or negative.
  268. */
  269. public static function randomString($minLength = 30, $maxLength = 30)
  270. {
  271. $str = Hashmark_Util::randomSha1();
  272. if ($maxLength > 0 && $maxLength < 41 && $minLength > 0 && $minLength <= $maxLength) {
  273. return substr($str, 0, mt_rand($minLength, $maxLength));
  274. }
  275. throw new Exception('Random string limits are invalid.', HASHMARK_EXCEPTION_VALIDATION);
  276. }
  277. /**
  278. * Testable logic for assertArrayContainsOnly().
  279. *
  280. * @static
  281. * @access public
  282. * @param mixed $needle Only expected element of $haystack.
  283. * @param Array $haystack
  284. * @param boolean $strict If true, $a === $b logic is used; othewise in_array().
  285. * @return boolean True if $haystack only contains one $needle.
  286. */
  287. public static function checkArrayContainsOnly($needle, $haystack, $strict = false)
  288. {
  289. if (!is_array($haystack) || count($haystack) != 1) {
  290. return false;
  291. }
  292. if ($strict) {
  293. $values = array_values($haystack);
  294. return $values[0] === $needle;
  295. } else {
  296. return in_array($needle, $haystack);
  297. }
  298. }
  299. /**
  300. * Assert $haystack contains only one element that is equal to $needle.
  301. *
  302. * - Uses assertTrue() internally to increment assertion count.
  303. *
  304. * @access public
  305. * @param mixed $needle Only expected element of $haystack.
  306. * @param Array $haystack
  307. * @param boolean $strict If true, $a === $b logic is used; othewise in_array().
  308. * @return void
  309. */
  310. public function assertArrayContainsOnly($needle, $haystack, $message = '')
  311. {
  312. if (self::checkArrayContainsOnly($needle, $haystack, $message)) {
  313. $this->assertTrue(true);
  314. } else {
  315. $needleType = gettype($needle);
  316. $needle = str_replace("\n", '', print_r($needle, true));
  317. $haystackType = gettype($haystack);
  318. $haystack = str_replace("\n", '', print_r($haystack, true));
  319. if ($message) {
  320. $message .= "\n";
  321. }
  322. $message .= "Failed asserting that Array <{$haystackType}:{$haystack}> "
  323. . "contains only element <{$needleType}:{$needle}>.";
  324. $this->assertTrue(false, $message);
  325. }
  326. }
  327. /**
  328. * Testable logic for assertDecimalEquals().
  329. *
  330. * @static
  331. * @access public
  332. * @param string $expected
  333. * @param string $actual
  334. * @return boolean True if equal.
  335. */
  336. public static function checkDecimalEquals($expected, $actual)
  337. {
  338. if (!is_string($expected) || !is_string($actual)) {
  339. return false;
  340. }
  341. bcscale(HASHMARK_DECIMAL_RIGHTWIDTH);
  342. return 0 === bccomp($expected, $actual);
  343. }
  344. /**
  345. * Uses bccomp() to check equality of two strings representing decimal values.
  346. *
  347. * - Uses assertTrue() internally to increment assertion count.
  348. *
  349. * @access public
  350. * @param string $expected
  351. * @param string $actual
  352. * @return void
  353. */
  354. public function assertDecimalEquals($expected, $actual, $message = '')
  355. {
  356. if (self::checkDecimalEquals($expected, $actual)) {
  357. $this->assertTrue(true);
  358. } else {
  359. $actualType = gettype($actual);
  360. $expectedType = gettype($expected);
  361. if ($message) {
  362. $message .= "\n";
  363. }
  364. $message .= "Failed asserting that actual decimal string <{$actualType}:"
  365. . "{$actual}> equals expected <{$expectedType}:{$expected}>.";
  366. $this->assertTrue(false, $message);
  367. }
  368. }
  369. }