p2 project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
9.6 KiB

2 months ago
<?php
declare(strict_types=1);
/**
* This file is part of the Carbon package.
*
* (c) Brian Nesbitt <brian@nesbot.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Tests;
use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Carbon\CarbonInterval;
use Carbon\CarbonPeriod;
use Carbon\CarbonPeriodImmutable;
use Carbon\CarbonTimeZone;
use Carbon\Translator;
use Closure;
use DateTime;
use ErrorException;
use PHPUnit\Framework\TestCase;
use ReflectionProperty;
use Tests\PHPUnit\AssertObjectHasPropertyTrait;
use Throwable;
/**
* @SuppressWarnings(PHPMD.NumberOfChildren)
*/
abstract class AbstractTestCase extends TestCase
{
use AssertObjectHasPropertyTrait;
private ?string $saveTz = null;
protected ?Carbon $now = null;
protected ?CarbonImmutable $immutableNow = null;
protected bool $oldNow = false;
protected bool $oldImmutableNow = false;
/** @var class-string<CarbonPeriod> */
protected static string $periodClass = CarbonPeriod::class;
protected int $initialOptions = 0;
protected function getTimestamp(): int
{
return (new DateTime())->getTimestamp();
}
protected function setUp(): void
{
$this->initialOptions = static::$periodClass === CarbonPeriodImmutable::class ? CarbonPeriod::IMMUTABLE : 0;
//save current timezone
$this->saveTz = date_default_timezone_get();
date_default_timezone_set('America/Toronto');
/** @var Carbon $now */
$now = $this->oldNow
? Carbon::create(2017, 6, 27, 13, 14, 15, 'UTC')
: Carbon::now();
/** @var CarbonImmutable $immutableNow */
$immutableNow = $this->oldImmutableNow
? CarbonImmutable::create(2017, 6, 27, 13, 14, 15, 'UTC')
: CarbonImmutable::now();
Carbon::setTestNowAndTimezone($this->now = $now);
CarbonImmutable::setTestNowAndTimezone($this->immutableNow = $immutableNow);
Carbon::useStrictMode(true);
CarbonImmutable::useStrictMode(true);
}
protected function tearDown(): void
{
date_default_timezone_set($this->saveTz);
Carbon::setTestNow();
Carbon::resetToStringFormat();
Carbon::resetMonthsOverflow();
Carbon::setTranslator(new Translator('en'));
Carbon::setLocale('en');
/** @var Translator $translator */
$translator = Carbon::getTranslator();
$translator->resetMessages();
CarbonImmutable::setTestNow();
CarbonImmutable::resetToStringFormat();
CarbonImmutable::resetMonthsOverflow();
CarbonImmutable::setTranslator(new Translator('en'));
CarbonImmutable::setLocale('en');
/** @var Translator $translator */
$translator = CarbonImmutable::getTranslator();
$translator->resetMessages();
}
public function assertCarbon(CarbonInterface $d, $year, $month, $day, $hour = null, $minute = null, $second = null, $micro = null): void
{
$expected = [
'years' => $year,
'months' => $month,
'day' => $day,
];
$actual = [
'years' => $d->year,
'months' => $d->month,
'day' => $d->day,
];
if ($hour !== null) {
$actual['hours'] = $d->hour;
$expected['hours'] = $hour;
}
if ($minute !== null) {
$actual['minutes'] = $d->minute;
$expected['minutes'] = $minute;
}
if ($second !== null) {
$actual['seconds'] = $d->second;
$expected['seconds'] = $second;
}
if ($micro !== null) {
$actual['micro'] = $d->micro;
$expected['micro'] = $micro;
}
$this->assertSame($expected, $actual);
}
public function assertCarbonTime(CarbonInterface $d, $hour = null, $minute = null, $second = null, $micro = null): void
{
$actual = [];
$expected = [];
if ($hour !== null) {
$actual['hours'] = $d->hour;
$expected['hours'] = $hour;
}
if ($minute !== null) {
$actual['minutes'] = $d->minute;
$expected['minutes'] = $minute;
}
if ($second !== null) {
$actual['seconds'] = $d->second;
$expected['seconds'] = $second;
}
if ($micro !== null) {
$actual['micro'] = $d->micro;
$expected['micro'] = $micro;
}
$this->assertSame($expected, $actual);
}
/**
* @phpstan-assert CarbonInterface $d
*/
public function assertInstanceOfCarbon($d): void
{
$this->assertInstanceOf(CarbonInterface::class, $d);
}
public function assertCarbonInterval(CarbonInterval $ci, $years, $months = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null, $inverted = null): void
{
$actual = ['years' => $ci->years];
$expected = ['years' => $years];
if ($months !== null) {
$actual['months'] = $ci->months;
$expected['months'] = $months;
}
if ($days !== null) {
$actual['days'] = $ci->dayz;
$expected['days'] = $days;
}
if ($hours !== null) {
$actual['hours'] = $ci->hours;
$expected['hours'] = $hours;
}
if ($minutes !== null) {
$actual['minutes'] = $ci->minutes;
$expected['minutes'] = $minutes;
}
if ($seconds !== null) {
$actual['seconds'] = $ci->seconds;
$expected['seconds'] = $seconds;
}
if ($microseconds !== null) {
$actual['microseconds'] = $ci->microseconds;
$expected['microseconds'] = $microseconds;
}
$this->assertSame($expected, $actual);
if ($inverted !== null) {
$this->assertSame((bool) $inverted, (bool) $ci->invert);
}
}
/**
* @phpstan-assert CarbonInterval $d
*/
public function assertInstanceOfCarbonInterval($d): void
{
$this->assertInstanceOf(CarbonInterval::class, $d);
}
public function wrapWithTestNow(Closure $func, ?CarbonInterface $dt = null): void
{
$test = Carbon::getTestNow();
$immutableTest = CarbonImmutable::getTestNow();
$dt = $dt ?: Carbon::now();
Carbon::setTestNowAndTimezone($dt);
CarbonImmutable::setTestNowAndTimezone($dt);
$func();
Carbon::setTestNowAndTimezone($test);
CarbonImmutable::setTestNowAndTimezone($immutableTest);
}
public function wrapWithNonDstDate(Closure $func): void
{
$this->wrapWithTestNow($func, Carbon::now()->startOfYear());
}
public function wrapWithUtf8LcTimeLocale($locale, Closure $func): void
{
$currentLocale = setlocale(LC_TIME, '0');
$locales = ["$locale.UTF-8", "$locale.utf8"];
$mapping = [
'fr_FR' => 'French_France',
];
$windowsLocale = $mapping[$locale] ?? null;
if ($windowsLocale) {
$locales[] = "$windowsLocale.UTF8";
}
if (setlocale(LC_TIME, ...$locales) === false) {
$this->markTestSkipped("UTF-8 test need $locale.UTF-8 (a locale with accents).");
}
try {
$func();
} finally {
setlocale(LC_TIME, $currentLocale);
}
}
public function withErrorAsException(Closure $func): void
{
$previous = set_error_handler(static function (int $code, string $message, string $file, int $line) {
throw new ErrorException($message, $code, $code, $file, $line);
});
$errorReporting = error_reporting();
try {
error_reporting(E_ALL);
$func();
} finally {
error_reporting($errorReporting);
restore_error_handler();
}
}
/**
* Standardize given set of dates (or period) before assertion.
*
* @param array|\DatePeriod $dates
*
* @return array
*/
public function standardizeDates($dates)
{
$result = [];
foreach ($dates as $date) {
if ($date instanceof DateTime) {
$date = Carbon::instance($date);
} elseif (\is_string($date)) {
$date = Carbon::parse($date);
}
$result[] = $date->format('Y-m-d H:i:s P');
}
return $result;
}
protected function areSameLocales($a, $b): bool
{
static $aliases = null;
if ($aliases === null) {
$property = new ReflectionProperty(Translator::class, 'aliases');
$aliases = $property->getValue(Translator::get());
}
$a = $aliases[$a] ?? $a;
$b = $aliases[$b] ?? $b;
return $a === $b;
}
protected function firstValidTimezoneAmong(array $timezones): CarbonTimeZone
{
$firstError = null;
foreach ($timezones as $timezone) {
try {
return new CarbonTimeZone($timezone);
} catch (Throwable $exception) {
$firstError = $firstError ?? $exception;
}
}
throw $firstError;
}
protected function assertPeriodOptions(int $options, CarbonPeriod $period): void
{
$this->assertSame($this->initialOptions | $options, $period->getOptions());
}
protected function assertVeryClose(mixed $expected, mixed $actual, string $message = ''): void
{
$this->assertEqualsWithDelta(
$expected,
$actual,
0.000000000000001,
$message,
);
}
}