Skip to content

Commit

Permalink
Introduce a diagnosis tool (#60)
Browse files Browse the repository at this point in the history
Introduce a way to diagnose a finder, i.e. get information about what a specific finder may find. Those are then aggregated and but run all by a diagnoser.

The idea of this tool is to provide a quick insight on how each finder will operator. For example on my machine:

```
$ make diagnose
./bin/diagnose.php
Running diagnosis...

CpuInfoFinder: 
--------------------------------------------
The file "/proc/cpuinfo" could not be found.
--------------------------------------------

DummyCpuCoreFinder(value=1): 
----------------
Will return "1".
----------------

HwLogicalFinder: 
---------------------------------------------------------------------------------
Executed the command "sysctl -n hw.logicalcpu 2>&1" and got the following output:
8

---------------------------------------------------------------------------------

HwPhysicalFinder: 
----------------------------------------------------------------------------------
Executed the command "sysctl -n hw.physicalcpu 2>&1" and got the following output:
8

----------------------------------------------------------------------------------

NProcFinder(all=true): 
----------------------------------------------------
The command "nproc --all" gave the following output:
8

----------------------------------------------------

NProcFinder(all=false): 
----------------------------------------------
The command "nproc" gave the following output:
8

----------------------------------------------

NullCpuCoreFinder: 
-------------------
Will return "null".
-------------------

WindowsWmicPhysicalFinder: 
--------------------------------------------------------------------------------------------------------------------------------------
Executed the command "wmic cpu get NumberOfProcessors 2>&1" which exited with a non-success exit code (127) with the following output:
sh: wmic: command not found

--------------------------------------------------------------------------------------------------------------------------------------

WindowsWmicLogicalFinder: 
---------------------------------------------------------------------------------------------------------------------------------------------
Executed the command "wmic cpu get NumberOfLogicalProcessors 2>&1" which exited with a non-success exit code (127) with the following output:
sh: wmic: command not found

---------------------------------------------------------------------------------------------------------------------------------------------


```

It also allows to execute each finders:

```
$ make execute
./bin/execute.php
Executing finders...

CpuInfoFinder: NULL
DummyCpuCoreFinder(value=1): 1
HwLogicalFinder: 8
HwPhysicalFinder: 8
NProcFinder(all=true): 8
NProcFinder(all=false): 8
NullCpuCoreFinder: NULL
WindowsWmicPhysicalFinder: NULL
WindowsWmicLogicalFinder: NULL

```

With this, it should be easy to test it on a specific system.
  • Loading branch information
theofidry authored Dec 7, 2022
1 parent 864d201 commit 7a6740d
Show file tree
Hide file tree
Showing 26 changed files with 652 additions and 141 deletions.
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ help:
default: ## Runs the default task: CS fix and all the tests
default: security cs autoreview test

.PHONY: diagnose
diagnose: ## Executes a diagnosis for all the finders
diagnose: vendor
./bin/diagnose.php

.PHONY: execute
execute: ## Executes all the finders
execute: vendor
./bin/execute.php

.PHONY: phive
phive: ## Updates a (registered) tool. E.g. make phive TOOL=infection
phive: $(PHIVE_BIN)
Expand Down
21 changes: 21 additions & 0 deletions bin/diagnose.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env php
<?php

/*
* This file is part of the Fidry CPUCounter Config package.
*
* (c) Théo FIDRY <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

use Fidry\CpuCoreCounter\Diagnoser;
use Fidry\CpuCoreCounter\Finder\FinderRegistry;

require_once __DIR__.'/../vendor/autoload.php';

echo 'Running diagnosis...'.PHP_EOL.PHP_EOL;
echo Diagnoser::diagnose(FinderRegistry::getAllVariants()).PHP_EOL;
21 changes: 21 additions & 0 deletions bin/execute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env php
<?php

/*
* This file is part of the Fidry CPUCounter Config package.
*
* (c) Théo FIDRY <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

use Fidry\CpuCoreCounter\Diagnoser;
use Fidry\CpuCoreCounter\Finder\FinderRegistry;

require_once __DIR__.'/../vendor/autoload.php';

echo 'Executing finders...'.PHP_EOL.PHP_EOL;
echo Diagnoser::execute(FinderRegistry::getAllVariants()).PHP_EOL;
29 changes: 5 additions & 24 deletions e2e/execute-finders.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,23 @@

declare(strict_types=1);

use Fidry\CpuCoreCounter\Finder\CpuInfoFinder;
use Fidry\CpuCoreCounter\Finder\DummyCpuCoreFinder;
use Fidry\CpuCoreCounter\Finder\HwLogicalFinder;
use Fidry\CpuCoreCounter\Finder\HwPhysicalFinder;
use Fidry\CpuCoreCounter\Finder\NProcFinder;
use Fidry\CpuCoreCounter\Finder\NullCpuCoreFinder;
use Fidry\CpuCoreCounter\Finder\WindowsWmicLogicalFinder;
use Fidry\CpuCoreCounter\Finder\WindowsWmicPhysicalFinder;
use Fidry\CpuCoreCounter\Test\Finder\LabeledFinder;
use Fidry\CpuCoreCounter\Finder\CpuCoreFinder;
use Fidry\CpuCoreCounter\Finder\FinderRegistry;

require_once __DIR__.'/../vendor/autoload.php';

$finders = [
new LabeledFinder(new CpuInfoFinder()),
new LabeledFinder(new DummyCpuCoreFinder(11)),
new LabeledFinder(new HwLogicalFinder()),
new LabeledFinder(new HwPhysicalFinder()),
new LabeledFinder(new NProcFinder(), 'NProcFinder{all=true}'),
new LabeledFinder(new NProcFinder(false), 'NProcFinder{all=false}'),
new LabeledFinder(new NullCpuCoreFinder()),
new LabeledFinder(new WindowsWmicLogicalFinder()),
new LabeledFinder(new WindowsWmicPhysicalFinder()),
];

$results = array_map(
static function (LabeledFinder $finder): string {
static function (CpuCoreFinder $finder): string {
return implode(
'',
[
$finder->getLabel(),
$finder->toString(),
': ',
null !== $finder->find() ? '.' : 'F',
]
);
},
$finders
FinderRegistry::getAllVariants()
);

echo implode(PHP_EOL, $results).PHP_EOL;
8 changes: 4 additions & 4 deletions e2e/expected-output
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
CpuInfoFinder: F
DummyCpuCoreFinder: .
DummyCpuCoreFinder(value=1): .
HwLogicalFinder: .
HwPhysicalFinder: .
NProcFinder{all=true}: .
NProcFinder{all=false}: .
NProcFinder(all=true): .
NProcFinder(all=false): .
NullCpuCoreFinder: F
WindowsWmicLogicalFinder: F
WindowsWmicPhysicalFinder: F
WindowsWmicLogicalFinder: F
99 changes: 99 additions & 0 deletions src/Diagnoser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

/*
* This file is part of the Fidry CPUCounter Config package.
*
* (c) Théo FIDRY <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Fidry\CpuCoreCounter;

use Fidry\CpuCoreCounter\Finder\CpuCoreFinder;
use function array_map;
use function explode;
use function implode;
use function max;
use function str_repeat;
use const PHP_EOL;

/**
* Utility to debug.
*
* @private
*/
final class Diagnoser
{
/**
* Provides an aggregated diagnosis based on each finders diagnosis.
*
* @param list<CpuCoreFinder> $finders
*/
public static function diagnose(array $finders): string
{
$diagnoses = array_map(
static fn (CpuCoreFinder $finder): string => self::diagnoseFinder($finder),
$finders
);

return implode(PHP_EOL, $diagnoses);
}

/**
* Executes each finders.
*
* @param list<CpuCoreFinder> $finders
*/
public static function execute(array $finders): string
{
$diagnoses = array_map(
static function (CpuCoreFinder $finder): string {
$coresCount = $finder->find();

return implode(
'',
[
$finder->toString(),
': ',
null === $coresCount ? 'NULL' : $coresCount,
]
);
},
$finders
);

return implode(PHP_EOL, $diagnoses);
}

private static function diagnoseFinder(CpuCoreFinder $finder): string
{
$diagnosis = $finder->diagnose();

$maxLineLength = max(
array_map(
'strlen',
explode(PHP_EOL, $diagnosis)
)
);

$separator = str_repeat('-', $maxLineLength);

return implode(
'',
[
$finder->toString().':'.PHP_EOL,
$separator.PHP_EOL,
$diagnosis.PHP_EOL,
$separator.PHP_EOL,
]
);
}

private function __construct()
{
}
}
15 changes: 15 additions & 0 deletions src/Finder/CpuCoreFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,22 @@
interface CpuCoreFinder
{
/**
* Provides an explanation which may offer some insight as to what the finder
* will be able to find.
*
* This is practical to have an idea of what each finder will find collect
* information for the unit tests, since integration tests are quite complicated
* as dependent on complex infrastructures.
*/
public function diagnose(): string;

/**
* Find the number of CPU cores. If it could not find it, returns null. The
* means used to find the cores are at the implementation discretion.
*
* @return positive-int|null
*/
public function find(): ?int;

public function toString(): string;
}
36 changes: 36 additions & 0 deletions src/Finder/CpuInfoFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@

use function file_get_contents;
use function is_file;
use function sprintf;
use function strrpos;
use function substr;
use function substr_count;
use const PHP_EOL;

/**
* Find the number of CPU cores looking up at the cpuinfo file which is available
Expand All @@ -28,6 +32,32 @@ final class CpuInfoFinder implements CpuCoreFinder
{
private const CPU_INFO_PATH = '/proc/cpuinfo';

public function diagnose(): string
{
if (!is_file(self::CPU_INFO_PATH)) {
return sprintf(
'The file "%s" could not be found.',
self::CPU_INFO_PATH
);
}

$cpuInfo = file_get_contents(self::CPU_INFO_PATH);

if (false === $cpuInfo) {
return sprintf(
'Could not get the content of the file "%s".',
self::CPU_INFO_PATH
);
}

return sprintf(
'Found the file "%s" with the content:%s%s',
self::CPU_INFO_PATH,
PHP_EOL,
$cpuInfo
);
}

/**
* @return positive-int|null
*/
Expand All @@ -38,6 +68,12 @@ public function find(): ?int
return null === $cpuInfo ? null : self::countCpuCores($cpuInfo);
}

public function toString(): string
{
/** @phpstan-ignore-next-line */
return substr(__CLASS__, strrpos(__CLASS__, '\\') + 1);
}

private static function getCpuInfo(): ?string
{
if (!is_file(self::CPU_INFO_PATH)) {
Expand Down
22 changes: 22 additions & 0 deletions src/Finder/DummyCpuCoreFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

namespace Fidry\CpuCoreCounter\Finder;

use function sprintf;
use function strrpos;
use function substr;

/**
* This finder returns whatever value you gave to it. This is useful for testing
* or as a fallback to avoid to catch the NumberOfCpuCoreNotFound exception.
Expand All @@ -24,6 +28,14 @@ final class DummyCpuCoreFinder implements CpuCoreFinder
*/
private $count;

public function diagnose(): string
{
return sprintf(
'Will return "%d".',
$this->count
);
}

/**
* @param positive-int $count
*/
Expand All @@ -36,4 +48,14 @@ public function find(): ?int
{
return $this->count;
}

public function toString(): string
{
return sprintf(
'%s(value=%d)',
/** @phpstan-ignore-next-line */
substr(__CLASS__, strrpos(__CLASS__, '\\') + 1),
$this->count
);
}
}
42 changes: 42 additions & 0 deletions src/Finder/FinderRegistry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

/*
* This file is part of the Fidry CPUCounter Config package.
*
* (c) Théo FIDRY <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Fidry\CpuCoreCounter\Finder;

/**
* @private
*/
final class FinderRegistry
{
/**
* @return list<CpuCoreFinder> List of all the known finders with all their variants.
*/
public static function getAllVariants(): array
{
return [
new CpuInfoFinder(),
new DummyCpuCoreFinder(1),
new HwLogicalFinder(),
new HwPhysicalFinder(),
new NProcFinder(true),
new NProcFinder(false),
new NullCpuCoreFinder(),
new WindowsWmicPhysicalFinder(),
new WindowsWmicLogicalFinder(),
];
}

private function __construct()
{
}
}
Loading

0 comments on commit 7a6740d

Please sign in to comment.