AbstractTestCase.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of the Carbon package.
  5. *
  6. * (c) Brian Nesbitt <brian@nesbot.com>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Tests;
  12. use Carbon\Carbon;
  13. use Carbon\CarbonImmutable;
  14. use Carbon\CarbonInterface;
  15. use Carbon\CarbonInterval;
  16. use Carbon\CarbonPeriod;
  17. use Carbon\CarbonTimeZone;
  18. use Carbon\Translator;
  19. use Closure;
  20. use DateTime;
  21. use PHPUnit\Framework\TestCase;
  22. use ReflectionProperty;
  23. use Tests\PHPUnit\AssertObjectHasPropertyTrait;
  24. use Throwable;
  25. /**
  26. * @SuppressWarnings(PHPMD.NumberOfChildren)
  27. */
  28. abstract class AbstractTestCase extends TestCase
  29. {
  30. use AssertObjectHasPropertyTrait;
  31. /**
  32. * @var \Carbon\Carbon
  33. */
  34. protected $now;
  35. /**
  36. * @var \Carbon\CarbonImmutable
  37. */
  38. protected $immutableNow;
  39. /**
  40. * @var bool
  41. */
  42. protected $oldNow = false;
  43. /**
  44. * @var bool
  45. */
  46. protected $oldImmutableNow = false;
  47. /**
  48. * @var string
  49. */
  50. private $saveTz;
  51. /**
  52. * @var class-string<CarbonPeriod>
  53. */
  54. protected $periodClass = CarbonPeriod::class;
  55. protected function getTimestamp()
  56. {
  57. return (new DateTime())->getTimestamp();
  58. }
  59. protected function setUp(): void
  60. {
  61. //save current timezone
  62. $this->saveTz = date_default_timezone_get();
  63. date_default_timezone_set('America/Toronto');
  64. /** @var Carbon $now */
  65. $now = $this->oldNow
  66. ? Carbon::create(2017, 6, 27, 13, 14, 15, 'UTC')
  67. : Carbon::now();
  68. /** @var CarbonImmutable $immutableNow */
  69. $immutableNow = $this->oldImmutableNow
  70. ? CarbonImmutable::create(2017, 6, 27, 13, 14, 15, 'UTC')
  71. : CarbonImmutable::now();
  72. Carbon::setTestNowAndTimezone($this->now = $now);
  73. CarbonImmutable::setTestNowAndTimezone($this->immutableNow = $immutableNow);
  74. Carbon::useStrictMode(true);
  75. CarbonImmutable::useStrictMode(true);
  76. }
  77. protected function tearDown(): void
  78. {
  79. date_default_timezone_set($this->saveTz);
  80. Carbon::setTestNow();
  81. Carbon::resetToStringFormat();
  82. Carbon::resetMonthsOverflow();
  83. Carbon::setTranslator(new Translator('en'));
  84. Carbon::setLocale('en');
  85. /** @var Translator $translator */
  86. $translator = Carbon::getTranslator();
  87. $translator->resetMessages();
  88. CarbonImmutable::setTestNow();
  89. CarbonImmutable::resetToStringFormat();
  90. CarbonImmutable::resetMonthsOverflow();
  91. CarbonImmutable::setTranslator(new Translator('en'));
  92. CarbonImmutable::setLocale('en');
  93. /** @var Translator $translator */
  94. $translator = CarbonImmutable::getTranslator();
  95. $translator->resetMessages();
  96. }
  97. public function assertCarbon(CarbonInterface $d, $year, $month, $day, $hour = null, $minute = null, $second = null, $micro = null)
  98. {
  99. $expected = [
  100. 'years' => $year,
  101. 'months' => $month,
  102. 'day' => $day,
  103. ];
  104. $actual = [
  105. 'years' => $d->year,
  106. 'months' => $d->month,
  107. 'day' => $d->day,
  108. ];
  109. if ($hour !== null) {
  110. $actual['hours'] = $d->hour;
  111. $expected['hours'] = $hour;
  112. }
  113. if ($minute !== null) {
  114. $actual['minutes'] = $d->minute;
  115. $expected['minutes'] = $minute;
  116. }
  117. if ($second !== null) {
  118. $actual['seconds'] = $d->second;
  119. $expected['seconds'] = $second;
  120. }
  121. if ($micro !== null) {
  122. $actual['micro'] = $d->micro;
  123. $expected['micro'] = $micro;
  124. }
  125. $this->assertSame($expected, $actual);
  126. }
  127. public function assertCarbonTime(CarbonInterface $d, $hour = null, $minute = null, $second = null, $micro = null)
  128. {
  129. $actual = [];
  130. $expected = [];
  131. if ($hour !== null) {
  132. $actual['hours'] = $d->hour;
  133. $expected['hours'] = $hour;
  134. }
  135. if ($minute !== null) {
  136. $actual['minutes'] = $d->minute;
  137. $expected['minutes'] = $minute;
  138. }
  139. if ($second !== null) {
  140. $actual['seconds'] = $d->second;
  141. $expected['seconds'] = $second;
  142. }
  143. if ($micro !== null) {
  144. $actual['micro'] = $d->micro;
  145. $expected['micro'] = $micro;
  146. }
  147. $this->assertSame($expected, $actual);
  148. }
  149. /**
  150. * @phpstan-assert CarbonInterface $d
  151. */
  152. public function assertInstanceOfCarbon($d)
  153. {
  154. $this->assertInstanceOf(CarbonInterface::class, $d);
  155. }
  156. public function assertCarbonInterval(CarbonInterval $ci, $years, $months = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null, $inverted = null)
  157. {
  158. $actual = ['years' => $ci->years];
  159. $expected = ['years' => $years];
  160. if ($months !== null) {
  161. $actual['months'] = $ci->months;
  162. $expected['months'] = $months;
  163. }
  164. if ($days !== null) {
  165. $actual['days'] = $ci->dayz;
  166. $expected['days'] = $days;
  167. }
  168. if ($hours !== null) {
  169. $actual['hours'] = $ci->hours;
  170. $expected['hours'] = $hours;
  171. }
  172. if ($minutes !== null) {
  173. $actual['minutes'] = $ci->minutes;
  174. $expected['minutes'] = $minutes;
  175. }
  176. if ($seconds !== null) {
  177. $actual['seconds'] = $ci->seconds;
  178. $expected['seconds'] = $seconds;
  179. }
  180. if ($microseconds !== null) {
  181. $actual['microseconds'] = $ci->microseconds;
  182. $expected['microseconds'] = $microseconds;
  183. }
  184. $this->assertSame($expected, $actual);
  185. if ($inverted !== null) {
  186. $this->assertSame((bool) $inverted, (bool) $ci->invert);
  187. }
  188. }
  189. /**
  190. * @phpstan-assert CarbonInterval $d
  191. */
  192. public function assertInstanceOfCarbonInterval($d)
  193. {
  194. $this->assertInstanceOf(CarbonInterval::class, $d);
  195. }
  196. public function wrapWithTestNow(Closure $func, CarbonInterface $dt = null)
  197. {
  198. $test = Carbon::getTestNow();
  199. $immutableTest = CarbonImmutable::getTestNow();
  200. $dt = $dt ?: Carbon::now();
  201. Carbon::setTestNowAndTimezone($dt);
  202. CarbonImmutable::setTestNowAndTimezone($dt);
  203. $func();
  204. Carbon::setTestNowAndTimezone($test);
  205. CarbonImmutable::setTestNowAndTimezone($immutableTest);
  206. }
  207. public function wrapWithNonDstDate(Closure $func)
  208. {
  209. $this->wrapWithTestNow($func, Carbon::now()->startOfYear());
  210. }
  211. public function wrapWithUtf8LcTimeLocale($locale, Closure $func)
  212. {
  213. $currentLocale = setlocale(LC_TIME, '0');
  214. $locales = ["$locale.UTF-8", "$locale.utf8"];
  215. $mapping = [
  216. 'fr_FR' => 'French_France',
  217. ];
  218. $windowsLocale = $mapping[$locale] ?? null;
  219. if ($windowsLocale) {
  220. $locales[] = "$windowsLocale.UTF8";
  221. }
  222. if (setlocale(LC_TIME, ...$locales) === false) {
  223. $this->markTestSkipped("UTF-8 test need $locale.UTF-8 (a locale with accents).");
  224. }
  225. $exception = null;
  226. try {
  227. $func();
  228. } catch (Throwable $e) {
  229. $exception = $e;
  230. }
  231. setlocale(LC_TIME, $currentLocale);
  232. if ($exception) {
  233. throw $exception;
  234. }
  235. }
  236. /**
  237. * Standardize given set of dates (or period) before assertion.
  238. *
  239. * @param array|\DatePeriod $dates
  240. *
  241. * @return array
  242. */
  243. public function standardizeDates($dates)
  244. {
  245. $result = [];
  246. foreach ($dates as $date) {
  247. if ($date instanceof DateTime) {
  248. $date = Carbon::instance($date);
  249. } elseif (\is_string($date)) {
  250. $date = Carbon::parse($date);
  251. }
  252. $result[] = $date->format('Y-m-d H:i:s P');
  253. }
  254. return $result;
  255. }
  256. protected function areSameLocales($a, $b)
  257. {
  258. static $aliases = null;
  259. if ($aliases === null) {
  260. $property = new ReflectionProperty(Translator::class, 'aliases');
  261. $property->setAccessible(true);
  262. $aliases = $property->getValue(Translator::get());
  263. }
  264. $a = $aliases[$a] ?? $a;
  265. $b = $aliases[$b] ?? $b;
  266. return $a === $b;
  267. }
  268. protected function firstValidTimezoneAmong(array $timezones): CarbonTimeZone
  269. {
  270. $firstError = null;
  271. foreach ($timezones as $timezone) {
  272. try {
  273. return new CarbonTimeZone($timezone);
  274. } catch (Throwable $exception) {
  275. $firstError = $firstError ?? $exception;
  276. }
  277. }
  278. throw $firstError;
  279. }
  280. }