From: Roland Häder Date: Wed, 22 Feb 2023 02:28:06 +0000 (+0100) Subject: Continued: X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=755901388ae4383f6bb4d1e0b1b635f74d924e58;p=core.git Continued: - introduced ConsoleTools::acquireHostname() which acquires own host's name - some methods of ConsoleTools are now "caching" their being "expensively" determined and then returned values - added more unit tests - added more debug lines --- diff --git a/framework/bootstrap/class_FrameworkBootstrap.php b/framework/bootstrap/class_FrameworkBootstrap.php index 79302a32..09895b37 100644 --- a/framework/bootstrap/class_FrameworkBootstrap.php +++ b/framework/bootstrap/class_FrameworkBootstrap.php @@ -187,30 +187,36 @@ final class FrameworkBootstrap { */ public static function isReachableFilePath (SplFileInfo $fileInstance) { // Is not reachable by default + //* NOISY-DEBUG: */ printf('[%s:%d]: fileInstance=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, get_class($fileInstance)); $isReachable = false; // Get open_basedir parameter $openBaseDir = trim(ini_get('open_basedir')); // Is it set? + //* NOISY-DEBUG: */ printf('[%s:%d]: openBaseDir=%s' . PHP_EOL, __METHOD__, __LINE__, $openBaseDir); if (!empty($openBaseDir)) { // Check all entries foreach (explode(PATH_SEPARATOR, $openBaseDir) as $dir) { // Check on existence + //* NOISY-DEBUG: */ printf('[%s:%d]: dir=%s' . PHP_EOL, __METHOD__, __LINE__, $dir); if (substr($fileInstance->getPathname(), 0, strlen($dir)) == $dir) { // Is reachable $isReachable = true; // Abort lookup as it has been found in open_basedir + //* NOISY-DEBUG: */ printf('[%s:%d]: BREAK!' . PHP_EOL, __METHOD__, __LINE__); break; } } } else { // If open_basedir is not set, all is allowed + //* NOISY-DEBUG: */ printf('[%s:%d]: All is allowed - BREAK!' . PHP_EOL, __METHOD__, __LINE__); $isReachable = true; } // Return status + //* NOISY-DEBUG: */ printf('[%s:%d]: isReachable=%d - EXIT' . PHP_EOL, __METHOD__, __LINE__, intval($isReachable)); return $isReachable; } diff --git a/framework/main/classes/class_BaseFrameworkSystem.php b/framework/main/classes/class_BaseFrameworkSystem.php index 0e9a1b44..d043576b 100644 --- a/framework/main/classes/class_BaseFrameworkSystem.php +++ b/framework/main/classes/class_BaseFrameworkSystem.php @@ -1869,7 +1869,7 @@ Loaded includes: * a configured temporary file path to it. * * @param $infoInstance An instance of a SplFileInfo class - * @return $tempInstance An instance of a SplFileInfo class (temporary file) + * @return $fileInfoInstance An instance of a SplFileInfo class (temporary file) * @throw PathWriteProtectedException If the path in 'temp_file_path' is write-protected * @throws FileIoException If the file cannot be written */ @@ -1886,17 +1886,17 @@ Loaded includes: } // Add it - $tempInstance = new SplFileInfo($basePath . DIRECTORY_SEPARATOR . $infoInstance->getBasename()); + $fileInfoInstance = new SplFileInfo($basePath . DIRECTORY_SEPARATOR . $infoInstance->getBasename()); // Is it reachable? - if (!FrameworkBootstrap::isReachableFilePath($tempInstance)) { + if (!FrameworkBootstrap::isReachableFilePath($fileInfoInstance)) { // Not reachable - throw new FileIoException($tempInstance, self::EXCEPTION_FILE_NOT_REACHABLE); + throw new FileIoException($fileInfoInstance, self::EXCEPTION_FILE_NOT_REACHABLE); } // Return it - //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-FRAMEWORK-SYSTEM: tempInstance=%s - EXIT!', $tempInstance->__toString())); - return $tempInstance; + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-FRAMEWORK-SYSTEM: fileInfoInstance=%s - EXIT!', $fileInfoInstance->__toString())); + return $fileInfoInstance; } /** diff --git a/framework/main/classes/tools/console/class_ConsoleTools.php b/framework/main/classes/tools/console/class_ConsoleTools.php index 02d29832..e9d2fe5a 100644 --- a/framework/main/classes/tools/console/class_ConsoleTools.php +++ b/framework/main/classes/tools/console/class_ConsoleTools.php @@ -47,6 +47,11 @@ class ConsoleTools extends BaseFrameworkSystem { */ private static $isQuietResolver = FALSE; + /** + * Cached values + */ + private static $cache = []; + /** * Protected constructor * @@ -269,61 +274,109 @@ class ConsoleTools extends BaseFrameworkSystem { } /** - * Aquires the IP address of this host by reading the /etc/hostname file - * and solving it. It is now stored in configuration + * acquires this host's LAN name. It tries a varity of different source. * - * @return $ipAddress Aquired IPv4 address + * @return $hostName The acquired name of this host or something invalid */ - public static function acquireSelfIpAddress () { - // Local IP by default - $ipAddress = '127.0.0.1'; + public static function acquireHostname () { + // Is cache there? + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('CONSOLE-TOOLS: CALLED!'); + if (!isset(self::$cache[__METHOD__])) { + // Get a new instance + $toolsInstance = new ConsoleTools(); - // Get a new instance - $helperInstance = new ConsoleTools(); + // Get SplFileInfo instance + $infoInstance = new SplFileInfo(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('hostname_file')); - // Get SplFileInfo instance - $infoInstance = new SplFileInfo(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('hostname_file')); + // Init host name + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('CONSOLE-TOOLS: infoInstance=%s', $infoInstance->__toString())); + $hostname = 'host.invalid'; - try { - // Get a file pointer - $fileInstance = ObjectFactory::createObjectByConfiguredName('file_raw_input_class', array($infoInstance)); + // Try to check /etc/hostname first + try { + // Get a file pointer + $fileInstance = ObjectFactory::createObjectByConfiguredName('file_raw_input_class', [$infoInstance]); - // Read the file - $rawData = trim($fileInstance->readFromFile()); + // Read the file + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('CONSOLE-TOOLS: fileInstance=%s', $fileInstance->__toString())); + $rawData = trim($fileInstance->readFromFile()); - // Close the file - $fileInstance->closeFile(); + // Close the file + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('CONSOLE-TOOLS: rawData=%s', $rawData)); + $fileInstance->closeFile(); - // Extract hostname from it - $hostname = $helperInstance->extractHostnameFromRawData($rawData); + // Extract hostname from it + $hostname = $toolsInstance->extractHostnameFromRawData($rawData); - // Resolve the IP number - $ipAddress = self::resolveIpAddress($hostname); - } catch (FileNotFoundException $e) { - // Fall-back to 'SESSION_SVR' which found on my Sun Station - if (isset($_SERVER['SESSION_SVR'])) { - // Resolve it - $ipAddress = self::resolveIpAddress($_SERVER['SESSION_SVR']); - } elseif (isset($_SERVER['COMPUTERNAME'])) { - // May happen on some Windows XP systems, so also try this - $ipAddress = self::resolveIpAddress($_SERVER['COMPUTERNAME']); - } else { - // Could not find our hostname - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:] WARNING: Cannot resolve my own IP address.', - $helperInstance->__toString() + // Debug message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('CONSOLE-TOOLS: hostname=%s from /etc/hostname', $hostname)); + } catch (FileNotFoundException $e) { + // Fall-back to 'SESSION_SVR' which found on my Sun Station + if (isset($_SERVER['SESSION_SVR'])) { + // Resolve it + $hostname = $_SERVER['SESSION_SVR']; + } elseif (isset($_SERVER['COMPUTERNAME'])) { + // May happen on some Windows XP systems, so also try this + $hostname = $_SERVER['COMPUTERNAME']; + } else { + // Could not find our hostname + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:] WARNING: Cannot acquire my own host name.', + $toolsInstance->__toString() + )); + } + + // Debug message + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('CONSOLE-TOOLS: hostname=%s from _SERVER array', $hostname)); + } catch (FrameworkException $e) { + // Output debug message + self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:] Problem while resolving own IP address: [%s|%s]:%s', + $toolsInstance->__toString(), + $e->__toString(), + $e->getHexCode(), + $e->getMessage() )); } - } catch (FrameworkException $e) { - // Output debug message - self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:] Problem while resolving own IP address: [%s|%s]:%s', - $helperInstance->__toString(), - $e->__toString(), - $e->getHexCode(), - $e->getMessage() - )); + + // Set cache + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('CONSOLE-TOOLS: Setting hostname=%s ...', $hostname)); + self::$cache[__METHOD__] = $hostname; + } else { + // Get from cache + $hostname = self::$cache[__METHOD__]; + } + + // Return it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('CONSOLE-TOOLS: hostname=%s - EXIT!', $hostname)); + return $hostname; + } + + /** + * acquires the IP address of this host by reading the /etc/hostname file + * and solving it. It is now stored in configuration + * + * @return $ipAddress acquired IPv4 address + */ + public static function acquireSelfIpAddress () { + // Is cache there? + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('CONSOLE-TOOLS: CALLED!'); + if (!isset(self::$cache[__METHOD__])) { + // Get host name + $hostname = self::acquireHostname(); + + // Resolve the IP number + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('CONSOLE-TOOLS: hostname=%s', $hostname)); + $ipAddress = self::resolveIpAddress($hostname); + + // Set cache + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('CONSOLE-TOOLS: Setting ipAddress=%s ...', $ipAddress)); + self::$cache[__METHOD__] = $ipAddress; + } else { + // Get it from cache + $ipAddress = self::$cache[__METHOD__]; } // Return it + /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('CONSOLE-TOOLS: ipAddress=%s - EXIT!', $ipAddress)); return $ipAddress; } @@ -346,13 +399,13 @@ class ConsoleTools extends BaseFrameworkSystem { */ public static function determineExternalAddress () { // Get helper instance - $helperInstance = new ConsoleTools(); + $toolsInstance = new ConsoleTools(); // First get a socket // @TODO Add some DNS caching here // Open connection - if ($helperInstance->isProxyUsed() === true) { + if ($toolsInstance->isProxyUsed() === true) { // Resolve hostname into IP address $ipAddress = self::resolveIpAddress(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('proxy_host')); @@ -366,26 +419,26 @@ class ConsoleTools extends BaseFrameworkSystem { // Check if there was an error else if ($errorNo > 0) { // Then throw again - throw new InvalidSocketException(array($helperInstance, $socketResource, $errorNo, $errorStr), BaseFrameworkSystem::EXCEPTION_INVALID_SOCKET); + throw new InvalidSocketException(array($toolsInstance, $socketResource, $errorNo, $errorStr), BaseFrameworkSystem::EXCEPTION_INVALID_SOCKET); } // Prepare the GET request - $request = 'GET ' . ($helperInstance->isProxyUsed() === true ? 'http://shipsimu.org' : '') . '/ip.php HTTP/1.0' . self::HTTP_EOL; + $request = 'GET ' . ($toolsInstance->isProxyUsed() === true ? 'http://shipsimu.org' : '') . '/ip.php HTTP/1.0' . self::HTTP_EOL; $request .= 'Host: shipsimu.org' . self::HTTP_EOL; $request .= 'User-Agent: ' . self::HTTP_USER_AGENT . self::HTTP_EOL; $request .= 'Connection: close' . self::HTTP_EOL; // Do we use proxy? - if ($helperInstance->isProxyUsed() === true) { + if ($toolsInstance->isProxyUsed() === true) { // CONNECT method? if (FrameworkBootstrap::getConfigurationInstance()->isEnabled('proxy_connect_method')) { // Setup proxy tunnel - $response = $helperInstance->setupProxyTunnel('shipsimu.org', 80, $socketResource); + $response = $toolsInstance->setupProxyTunnel('shipsimu.org', 80, $socketResource); // If the response is invalid, abort if ((count($response) == 3) && (empty($response[0])) && (empty($response[1])) && (empty($response[2]))) { // Invalid response! - $helperInstance->debugBackTrace('Proxy tunnel not working: response=' . print_r($response, true)); + $toolsInstance->debugBackTrace('Proxy tunnel not working: response=' . print_r($response, true)); } } else { // Add header for proxy diff --git a/tests/framework/bootstrap/class_FrameworkBootstrapTest.php b/tests/framework/bootstrap/class_FrameworkBootstrapTest.php index e7a8ccfb..289c2433 100644 --- a/tests/framework/bootstrap/class_FrameworkBootstrapTest.php +++ b/tests/framework/bootstrap/class_FrameworkBootstrapTest.php @@ -6,6 +6,7 @@ namespace Org\Mxchange\CoreFramework\Bootstrap; use Org\Mxchange\CoreFramework\Console\Tools\ConsoleTools; use Org\Mxchange\CoreFramework\Generic\NullPointerException; use Org\Mxchange\CoreFramework\Generic\UnsupportedOperationException; +use Org\Mxchange\CoreFramework\Loader\ClassLoader; // Import PHPUnit stuff use PHPUnit\Framework\Error\Notice; @@ -13,6 +14,7 @@ use PHPUnit\Framework\TestCase; // Import SPL stuff use \InvalidArgumentException; +use \SplFileInfo; /* * Copyright (C) 2017 - 2023 Core Developer Team @@ -35,7 +37,12 @@ class FrameworkBootstrapTest extends TestCase { /** * Own IP address */ - private static $ipAddress = FALSE; + private static $ipAddress = '0.0.0.0'; + + /** + * Own host name + */ + private static $hostname = 'host.invalid'; /** * Setup test case @@ -49,7 +56,6 @@ class FrameworkBootstrapTest extends TestCase { // Trace message //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__); - } /** @@ -57,16 +63,19 @@ class FrameworkBootstrapTest extends TestCase { */ public static function setUpBeforeClass() { // Trace message - //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__); + /* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__); // Call parent method parent::setUpBeforeClass(); + // Lookup own hostname + self::$hostname = ConsoleTools::acquireHostname(); + // Lookup own IP address self::$ipAddress = ConsoleTools::acquireSelfIpAddress(); // Trace message - //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__); + /* NOISY-DEBUG: */ printf('[%s:%d]: self::ipAddress[%s]=%s,self::hostname=%s - EXIT!' . PHP_EOL, __METHOD__, __LINE__, gettype(self::$ipAddress), self::$ipAddress, self::$hostname); } /** @@ -103,7 +112,7 @@ class FrameworkBootstrapTest extends TestCase { * Tests if detectServerAddress() is returning what it should for tests. * This will always be 127.0.0.1. */ - public function testConfigDetectServerAddress () { + public function testBootstrapDetectServerAddress () { // Call it $serverAddress = FrameworkBootstrap::detectServerAddress(); @@ -116,12 +125,113 @@ class FrameworkBootstrapTest extends TestCase { * This will always be 127.0.0.1. This method should not invoke * ConsoleTools's method as the configuration entry is already cached. */ - public function testConfigDetectServerAddressCached () { + public function testBootstrapDetectServerAddressCached () { // Call it + //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__); $serverAddress = FrameworkBootstrap::detectServerAddress(); // Should be the same + //* NOISY-DEBUG: */ printf('[%s:%d]: self::ipAddress=%s,serverAddress=%s' . PHP_EOL, __METHOD__, __LINE__, self::$ipAddress, $serverAddress); $this->assertEquals(self::$ipAddress, $serverAddress); + + // Trace message + //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__); + } + + /** + * Tests method BootstrapFramework::isReachableFilePath() with a + * non-existing path. $isReachable should always return TRUE as nothing is + * restricting PHP. + */ + public function testBootstrapIsReachableFilePathUnrestrictedNotExisting () { + // Init SPL file info instance + //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__); + $infoInstance = new SplFileInfo('/does/not/exist/'); + + // Invoke method + /* NOISY-DEBUG: */ printf('[%s:%d]: infoInstance=%s' . PHP_EOL, __METHOD__, __LINE__, get_class($infoInstance)); + $isReachable = FrameworkBootstrap::isReachableFilePath($infoInstance); + + // Test if it is not reachable + /* NOISY-DEBUG: */ printf('[%s:%d]: isReachable=%d' . PHP_EOL, __METHOD__, __LINE__, intval($isReachable)); + $this->assertTrue($isReachable, 'Returned true on a non-existing path'); + + // Trace message + //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__); + } + + /** + * Tests method BootstrapFramework::isReachableFilePath() with a + * non-existing path. $isReachable should be FALSE here as it is always + * outside the scope of open_basedir. + */ + public function testBootstrapIsReachableFilePathRestrictedNotExisting () { + // Init SPL file info instance + //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__); + $infoInstance = new SplFileInfo('/does/not/exist/'); + + // "Detect" root path + //* NOISY-DEBUG: */ printf('[%s:%d]: infoInstance=%s' . PHP_EOL, __METHOD__, __LINE__, get_class($infoInstance)); + $rootScriptPath = realpath(dirname(dirname(FrameworkBootstrap::detectScriptPath()))); + + // Set it + /* NOISY-DEBUG: */ printf('[%s:%d]: open_basedir=%s,rootScriptPath[%s]=%s' . PHP_EOL, __METHOD__, __LINE__, ini_get('open_basedir'), gettype($rootScriptPath), $rootScriptPath); + $result = ini_set('open_basedir', $rootScriptPath . ':/etc/'); + + // Was it set? + //* NOISY-DEBUG: */ printf('[%s:%d]: result[]=%s' . PHP_EOL, __METHOD__, __LINE__, gettype($result)); + if ($result === FALSE) { + // Didn't work + $this->failed(sprintf('Cannot set open_basepath=%s', $rootScriptPath)); + } + + // Invoke method + //* NOISY-DEBUG: */ printf('[%s:%d]: Testing method FrameworkBootstrap::isReachableFilePath(%s) ...' . PHP_EOL, __METHOD__, __LINE__, get_class($infoInstance)); + $isReachable = FrameworkBootstrap::isReachableFilePath($infoInstance); + + // Test if + //* NOISY-DEBUG: */ printf('[%s:%d]: isReachable=%d - Testing method ...' . PHP_EOL, __METHOD__, __LINE__, intval($isReachable)); + $this->assertTrue(!$isReachable, 'Returned true on a non-existing path'); + + // Trace message + //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__); + } + + /** + * Tests method BootstrapFramework::isReachableFilePath() with an + * existing path. $isReachable should be TRUE here as it is within the scope + * of open_basedir. + */ + public function testBootstrapIsReachableFilePathRestrictedExisting () { + // Init SPL file info instance + //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__); + $infoInstance = new SplFileInfo(__DIR__); + + // "Detect" root path + //* NOISY-DEBUG: */ printf('[%s:%d]: infoInstance=%s' . PHP_EOL, __METHOD__, __LINE__, get_class($infoInstance)); + $rootScriptPath = realpath(dirname(dirname(FrameworkBootstrap::detectScriptPath()))); + + // Set it + //* NOISY-DEBUG: */ printf('[%s:%d]: rootScriptPath[%s]=%s' . PHP_EOL, __METHOD__, __LINE__, gettype($rootScriptPath), $rootScriptPath); + $result = ini_set('open_basedir', $rootScriptPath . ':/etc/'); + + // Was it set? + //* NOISY-DEBUG: */ printf('[%s:%d]: result[]=%s' . PHP_EOL, __METHOD__, __LINE__, gettype($result)); + if ($result === FALSE) { + // Didn't work + $this->failed(sprintf('Cannot set open_basepath=%s', $rootScriptPath)); + } + + // Invoke method + //* NOISY-DEBUG: */ printf('[%s:%d]: Testing method FrameworkBootstrap::isReachableFilePath(%s) ...' . PHP_EOL, __METHOD__, __LINE__, get_class($infoInstance)); + $isReachable = FrameworkBootstrap::isReachableFilePath($infoInstance); + + // Test if + //* NOISY-DEBUG: */ printf('[%s:%d]: isReachable=%d - Testing method ...' . PHP_EOL, __METHOD__, __LINE__, intval($isReachable)); + $this->assertTrue($isReachable, 'Returned true on a non-existing path'); + + // Trace message + //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__); } } diff --git a/tests/framework/config/FrameworkConfigurationTest.php b/tests/framework/config/FrameworkConfigurationTest.php index 27fdc26b..3a2db60b 100644 --- a/tests/framework/config/FrameworkConfigurationTest.php +++ b/tests/framework/config/FrameworkConfigurationTest.php @@ -394,4 +394,28 @@ class FrameworkConfigurationTest extends TestCase { $this->assertTrue(is_bool(self::$configInstance->isEnabled('single_server'))); } + /** + * Tests if sorting the configuration array is always returning the same + * array (but sorted) back. + */ + public function testConfigSortConfigurationArray () { + // First get configuration array + /* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__); + $config = self::$configInstance->getConfigurationArray(); + + // Run sort method + /* NOISY-DEBUG: */ printf('[%s:%d]: config()=%d' . PHP_EOL, __METHOD__, __LINE__, count($config)); + self::$configInstance->sortConfigurationArray(); + + // This should be an empty array + $diff = array_diff($config, self::$configInstance->getConfigurationArray()); + + // Check condition + /* NOISY-DEBUG: */ printf('[%s:%d]: diff()=%d' . PHP_EOL, __METHOD__, __LINE__, count($diff)); + $this->assertTrue(count($diff) === 0); + + // Trace message + /* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__); + } + }