Skip to content

Commit

Permalink
Merge pull request #196 from mimmi20/updates
Browse files Browse the repository at this point in the history
update tests
  • Loading branch information
mimmi20 authored May 29, 2023
2 parents f916fda + 14e7b60 commit 313ebe1
Show file tree
Hide file tree
Showing 7 changed files with 3,116 additions and 367 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ jobs:
- name: "Run mutation tests with infection/infection"
env:
STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }}
run: "vendor/bin/infection --show-mutations --only-covered --min-covered-msi=79 --min-msi=79 --coverage=.build/coverage --logger-github --no-progress -vv"
run: "vendor/bin/infection --show-mutations --only-covered --min-covered-msi=97 --min-msi=97 --coverage=.build/coverage --logger-github --no-progress -vv"

# This is a meta job to avoid to have to constantly change the protection rules
# whenever we touch the matrix.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"infection/infection": "^0.27.0",
"laminas/laminas-modulemanager": "^2.14.0",
"laminas/laminas-servicemanager": "^3.21.0",
"mimmi20/coding-standard": "^5.0.3",
"mimmi20/coding-standard": "^5.0.5",
"nikic/php-parser": "^v4.15.5",
"phpstan/extension-installer": "^1.3.1",
"phpstan/phpstan": "^1.10.15",
Expand Down
1 change: 1 addition & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<exclude name="SlevomatCodingStandard.Classes.ClassLength.ClassTooLong"/>
<exclude name="SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh"/>
<exclude name="SlevomatCodingStandard.Files.FileLength.FileTooLong"/>
<exclude name="Generic.Metrics.CyclomaticComplexity"/>
</rule>

<!-- Paths to check -->
Expand Down
231 changes: 133 additions & 98 deletions src/StreamFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

namespace Mimmi20\Monolog\Formatter;

use DateTimeImmutable;
use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Level;
Expand All @@ -28,16 +27,11 @@
use function array_keys;
use function count;
use function is_array;
use function is_bool;
use function is_iterable;
use function is_scalar;
use function is_string;
use function mb_strpos;
use function str_repeat;
use function str_replace;
use function trim;
use function ucfirst;
use function var_export;

final class StreamFormatter extends NormalizerFormatter
{
Expand Down Expand Up @@ -128,10 +122,6 @@ public function setFormatter(LineFormatter $formatter): void
*/
public function format(LogRecord $record): string
{
/** @var array<(array|scalar|null)>|scalar|null $vars */
/** @phpstan-var array{message: string, context: array<mixed>, level: Level, level_name: string, channel: string, datetime: DateTimeImmutable, extra: array<mixed>} $vars */
$vars = $this->normalizeRecord($record);

$message = $this->getFormatter()->format($record);

$levelName = Level::fromValue($record->level->value)->getName();
Expand Down Expand Up @@ -172,65 +162,8 @@ public function format(LogRecord $record): string
],
);

foreach (['extra', 'context'] as $element) {
if (empty($vars[$element]) || !is_iterable($vars[$element])) {
continue;
}

$this->table->addRow(new TableSeparator());
$this->table->addRow(
[new TableCell(ucfirst($element), ['colspan' => self::SPAN_ALL_COLUMS])],
);
$this->table->addRow(new TableSeparator());

foreach ($vars[$element] as $key => $value) {
if (!is_string($key)) {
continue;
}

if (
is_array($record->{$element})
&& isset($record->{$element}[$key])
&& $record->{$element}[$key] instanceof Throwable
) {
$exception = $record->{$element}[$key];

$value = [
'Code' => $exception->getCode(),
'File' => $exception->getFile(),
'Line' => $exception->getLine(),
'Message' => $exception->getMessage(),
'Trace' => $exception->getTraceAsString(),
'Type' => $exception::class,
];

$this->addFact($key, $value);

$prev = $exception->getPrevious();

if ($prev instanceof Throwable) {
do {
$value = [
'Code' => $prev->getCode(),
'File' => $prev->getFile(),
'Line' => $prev->getLine(),
'Message' => $prev->getMessage(),
'Trace' => $prev->getTraceAsString(),
'Type' => $prev::class,
];

$this->addFact('previous Throwable', $value);

$prev = $prev->getPrevious();
} while ($prev instanceof Throwable);
}

continue;
}

$this->addFact($key, $value);
}
}
$this->addExtra($record->extra);
$this->addContext($record->context);

$this->table->render();

Expand Down Expand Up @@ -272,38 +205,98 @@ private function getFormatter(): LineFormatter
return $this->formatter;
}

/** @throws RuntimeException if encoding fails and errors are not ignored */
private function stringify(mixed $value): string
/**
* @param array<mixed> $context
*
* @throws RuntimeException
*/
private function addContext(array $context): void
{
return $this->replaceNewlines($this->convertToString($value));
if ($context === []) {
return;
}

$this->table->addRow(new TableSeparator());
$this->table->addRow(
[new TableCell('Context', ['colspan' => self::SPAN_ALL_COLUMS])],
);
$this->table->addRow(new TableSeparator());

foreach ($context as $key => $value) {
if (!is_string($key)) {
continue;
}

$this->addFact($key, $this->normalize($value));
}
}

/** @throws RuntimeException if encoding fails and errors are not ignored */
private function convertToString(mixed $data): string
/**
* @param array<mixed> $extra
*
* @throws RuntimeException
*/
private function addExtra(array $extra): void
{
if ($data === null || is_bool($data)) {
return var_export($data, true);
if ($extra === []) {
return;
}

if (is_scalar($data)) {
return (string) $data;
}
$this->table->addRow(new TableSeparator());
$this->table->addRow(
[new TableCell('Extra', ['colspan' => self::SPAN_ALL_COLUMS])],
);
$this->table->addRow(new TableSeparator());

return $this->toJson($data, true);
foreach ($extra as $key => $value) {
if (!is_string($key)) {
continue;
}

if ($extra[$key] instanceof Throwable) {
$this->addThrowable($extra[$key]);

continue;
}

$this->addFact($key, $this->normalize($value));
}
}

/** @throws void */
private function replaceNewlines(string $str): string
/** @throws RuntimeException */
private function addThrowable(Throwable $exception): void
{
if ($this->allowInlineLineBreaks) {
if (mb_strpos($str, '{') === 0) {
return str_replace(['\r', '\n'], ["\r", "\n"], $str);
}
$value = [
'Code' => $exception->getCode(),
'File' => $exception->getFile(),
'Line' => $exception->getLine(),
'Message' => $exception->getMessage(),
'Trace' => $exception->getTraceAsString(),
'Type' => $exception::class,
];

$this->addFact('Throwable', $value);

return $str;
$prev = $exception->getPrevious();

if (!$prev instanceof Throwable) {
return;
}

return str_replace(["\r\n", "\r", "\n"], ' ', $str);
do {
$value = [
'Code' => $prev->getCode(),
'File' => $prev->getFile(),
'Line' => $prev->getLine(),
'Message' => $prev->getMessage(),
'Trace' => $prev->getTraceAsString(),
'Type' => $prev::class,
];

$this->addFact('previous Throwable', $value);

$prev = $prev->getPrevious();
} while ($prev instanceof Throwable);
}

/** @throws RuntimeException if encoding fails and errors are not ignored */
Expand All @@ -315,11 +308,7 @@ private function addFact(string $name, mixed $value): void
$rowspan = count($value);

foreach (array_keys($value) as $number => $key) {
$cellValue = $value[$key];

if (!is_string($cellValue)) {
$cellValue = $this->stringify($cellValue);
}
$cellValue = $this->stringify($value[$key]);

if ($number === 0) {
$this->table->addRow(
Expand All @@ -341,17 +330,17 @@ private function addFact(string $name, mixed $value): void
),
],
);
} else {
$this->table->addRow([new TableCell((string) $key), new TableCell($cellValue)]);

continue;
}

$this->table->addRow([new TableCell((string) $key), new TableCell($cellValue)]);
}

return;
}

if (!is_string($value)) {
$value = $this->stringify($value);
}
$value = $this->stringify($value);

$this->table->addRow(
[
Expand All @@ -363,4 +352,50 @@ private function addFact(string $name, mixed $value): void
],
);
}

/** @throws RuntimeException if encoding fails and errors are not ignored */
private function stringify(mixed $value): string
{
return $this->replaceNewlines($this->convertToString($value));
}

/** @throws RuntimeException if encoding fails and errors are not ignored */
private function convertToString(mixed $data): string
{
if (is_string($data)) {
return $data;
}

if ($data === null) {
return 'null';
}

if ($data === true) {
return 'true';
}

if ($data === false) {
return 'false';
}

if (is_scalar($data)) {
return (string) $data;
}

return $this->toJson($data, true);
}

/** @throws void */
private function replaceNewlines(string $str): string
{
if ($this->allowInlineLineBreaks) {
return str_replace(
['\\\\r\\\\n', '\\r\\n', '\\\\r', '\\r', '\\\\n', '\\n', "\r\n", "\r"],
"\n",
$str,
);
}

return str_replace(["\r\n", "\r", "\n"], ' ', $str);
}
}
31 changes: 31 additions & 0 deletions tests/ConfigProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,35 @@ public function testGetMonologFormatterConfig(): void
self::assertIsArray($factories);
self::assertCount(1, $factories);
}

/** @throws Exception */
public function testInvoke(): void
{
$config = ($this->provider)();
self::assertIsArray($config);
self::assertCount(1, $config);

self::assertArrayHasKey('monolog_formatters', $config);

$monologFormatterConfig = $config['monolog_formatters'];
self::assertIsArray($monologFormatterConfig);
self::assertCount(2, $monologFormatterConfig);

self::assertArrayNotHasKey('abstract_factories', $monologFormatterConfig);
self::assertArrayNotHasKey('delegators', $monologFormatterConfig);
self::assertArrayNotHasKey('initializers', $monologFormatterConfig);
self::assertArrayNotHasKey('invokables', $monologFormatterConfig);
self::assertArrayNotHasKey('services', $monologFormatterConfig);
self::assertArrayNotHasKey('shared', $monologFormatterConfig);

self::assertArrayHasKey('aliases', $monologFormatterConfig);
$aliases = $monologFormatterConfig['aliases'];
self::assertIsArray($aliases);
self::assertCount(1, $aliases);

self::assertArrayHasKey('factories', $monologFormatterConfig);
$factories = $monologFormatterConfig['factories'];
self::assertIsArray($factories);
self::assertCount(1, $factories);
}
}
21 changes: 21 additions & 0 deletions tests/ModuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,26 @@ public function testGetConfig(): void
self::assertIsArray($config);
self::assertCount(1, $config);
self::assertArrayHasKey('monolog_formatters', $config);

$monologFormatterConfig = $config['monolog_formatters'];
self::assertIsArray($monologFormatterConfig);
self::assertCount(2, $monologFormatterConfig);

self::assertArrayNotHasKey('abstract_factories', $monologFormatterConfig);
self::assertArrayNotHasKey('delegators', $monologFormatterConfig);
self::assertArrayNotHasKey('initializers', $monologFormatterConfig);
self::assertArrayNotHasKey('invokables', $monologFormatterConfig);
self::assertArrayNotHasKey('services', $monologFormatterConfig);
self::assertArrayNotHasKey('shared', $monologFormatterConfig);

self::assertArrayHasKey('aliases', $monologFormatterConfig);
$aliases = $monologFormatterConfig['aliases'];
self::assertIsArray($aliases);
self::assertCount(1, $aliases);

self::assertArrayHasKey('factories', $monologFormatterConfig);
$factories = $monologFormatterConfig['factories'];
self::assertIsArray($factories);
self::assertCount(1, $factories);
}
}
Loading

0 comments on commit 313ebe1

Please sign in to comment.