Skip to content

Commit

Permalink
Check whether passthru() is disabled
Browse files Browse the repository at this point in the history
If passthru() is disabled in php.ini, this will force the
SystemNodeProvider to return `false` for the node. Using the default
FallbackNodeProvider, ramsey/uuid will default to the
RandomNodeProvider, in these cases.

Closes #114
  • Loading branch information
ramsey committed Jul 19, 2018
1 parent 735eb7e commit 8d62148
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 31 deletions.
4 changes: 4 additions & 0 deletions src/Provider/Node/SystemNodeProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ public function getNode()
*/
protected function getIfconfig()
{
if (strpos(strtolower(ini_get('disable_functions')), 'passthru') !== false) {
return '';
}

ob_start();
switch (strtoupper(substr(php_uname('a'), 0, 3))) {
case 'WIN':
Expand Down
117 changes: 86 additions & 31 deletions tests/Provider/Node/SystemNodeProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* - php_uname
* - passthru
* - file_get_contents
* - ini_get
*
* On Linux systems `glob` would normally provide one or more paths were mac
* address can be retrieved (using `file_get_contents`). On non-linux systems,
Expand All @@ -37,6 +38,7 @@ class SystemNodeProviderTest extends TestCase
const MOCK_UNAME = 'php_uname';
const MOCK_PASSTHRU = 'passthru';
const MOCK_FILE_GET_CONTENTS = 'file_get_contents';
const MOCK_INI_GET = 'ini_get';

const PROVIDER_NAMESPACE = 'Ramsey\\Uuid\\Provider\\Node';

Expand All @@ -61,15 +63,16 @@ public function testGetNodeReturnsSystemNodeFromMacAddress($netstatOutput, $expe
function () use ($netstatOutput) {
echo $netstatOutput;
},
'NOT LINUX'
'NOT LINUX',
'nothing disabled'
);

/*/ Act upon the system under test/*/
$provider = new SystemNodeProvider();
$node = $provider->getNode();

/*/ Assert the result match expectations /*/
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);

$this->assertSame($expected, $node);

Expand Down Expand Up @@ -97,15 +100,16 @@ public function testGetNodeShouldNotReturnsSystemNodeForInvalidMacAddress($netst
function () use ($netstatOutput) {
echo $netstatOutput;
},
'NOT LINUX'
'NOT LINUX',
'nothing disabled'
);

/*/ Act /*/
$provider = new SystemNodeProvider();
$node = $provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);

$this->assertFalse($node);
}
Expand All @@ -128,15 +132,16 @@ public function testGetNodeReturnsNodeStrippedOfNotationalFormatting($formatted,
function () use ($formatted) {
echo "\n{$formatted}\n";
},
'NOT LINUX'
'NOT LINUX',
'nothing disabled'
);

/*/ Act /*/
$provider = new SystemNodeProvider();
$node = $provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);

$this->assertEquals($expected, $node);
}
Expand All @@ -158,15 +163,16 @@ public function testGetNodeDoesNotAcceptIncorrectNotationalFormatting($formatted
function () use ($formatted) {
echo "\n{$formatted}\n";
},
'NOT LINUX'
'NOT LINUX',
'nothing disabled'
);

/*/ Act /*/
$provider = new SystemNodeProvider();
$node = $provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);

$this->assertEquals(false, $node);
}
Expand All @@ -184,15 +190,16 @@ public function testGetNodeReturnsFirstMacAddressFound()
function () {
echo "\nAA-BB-CC-DD-EE-FF\n00-11-22-33-44-55\nFF-11-EE-22-DD-33\n";
},
'NOT LINUX'
'NOT LINUX',
'nothing disabled'
);

/*/ Act /*/
$provider = new SystemNodeProvider();
$node = $provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);

$this->assertEquals('AABBCCDDEEFF', $node);
}
Expand All @@ -210,15 +217,16 @@ public function testGetNodeReturnsFalseWhenNodeIsNotFound()
function () {
echo 'some string that does not match the mac address';
},
'NOT LINUX'
'NOT LINUX',
'nothing disabled'
);

/*/ Act /*/
$provider = new SystemNodeProvider();
$node = $provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);

$this->assertFalse($node);
}
Expand All @@ -236,7 +244,8 @@ public function testGetNodeWillNotExecuteSystemCallIfFailedFirstTime()
function () {
echo 'some string that does not match the mac address';
},
'NOT LINUX'
'NOT LINUX',
'nothing disabled'
);

/*/ Act /*/
Expand All @@ -245,7 +254,7 @@ function () {
$provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);
}

/**
Expand All @@ -266,10 +275,10 @@ public function testGetNodeGetsNetworkInterfaceConfig($os, $command)
'whatever',
['mock address path'],
'whatever',
$os
$os,
'nothing disabled'
);


/*/ Act /*/
$provider = new SystemNodeProvider();
$provider->getNode();
Expand All @@ -281,7 +290,7 @@ public function testGetNodeGetsNetworkInterfaceConfig($os, $command)
$globBodyAssert = ['/sys/class/net/*/address'];
$fileGetContentsAssert = ['mock address path'];
}
$this->assertMockFunctions($fileGetContentsAssert, $globBodyAssert, [$command], [['a'], ['s']]);
$this->assertMockFunctions($fileGetContentsAssert, $globBodyAssert, [$command], [['a'], ['s']], ['disable_functions']);
}

/**
Expand All @@ -297,7 +306,8 @@ public function testGetNodeReturnsSameNodeUponSubsequentCalls()
function () {
echo "\nAA-BB-CC-DD-EE-FF\n";
},
'NOT LINUX'
'NOT LINUX',
'nothing disabled'
);

/*/ Act /*/
Expand All @@ -306,7 +316,7 @@ function () {
$node2 = $provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);

$this->assertEquals($node, $node2);
}
Expand All @@ -324,7 +334,8 @@ public function testSubsequentCallsToGetNodeDoNotRecallIfconfig()
function () {
echo "\nAA-BB-CC-DD-EE-FF\n";
},
'NOT LINUX'
'NOT LINUX',
'nothing disabled'
);

/*/ Act /*/
Expand All @@ -333,7 +344,7 @@ function () {
$node2 = $provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, null, ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);

$this->assertEquals($node, $node2);
}
Expand All @@ -359,7 +370,8 @@ function () {
function () {
echo "\n01-02-03-04-05-06\n";
},
$os
$os,
'nothing disabled'
);

/*/ Act /*/
Expand All @@ -371,14 +383,16 @@ function () {
$globBodyAssert = null;
$passthruBodyAssert = [$command];
$unameBodyAssert = [['a'], ['s']];
$iniGetDisableFunctionsAssert = ['disable_functions'];

if ($os === 'Linux') {
$fileGetContentsAssert = [['mock address path 1'], ['mock address path 2']];
$globBodyAssert = ['/sys/class/net/*/address'];
$passthruBodyAssert = null;
$unameBodyAssert = ['s'];
$iniGetDisableFunctionsAssert = null;
}
$this->assertMockFunctions($fileGetContentsAssert, $globBodyAssert, $passthruBodyAssert, $unameBodyAssert);
$this->assertMockFunctions($fileGetContentsAssert, $globBodyAssert, $passthruBodyAssert, $unameBodyAssert, $iniGetDisableFunctionsAssert);

$this->assertEquals('010203040506', $node);
}
Expand All @@ -396,15 +410,16 @@ public function testCallGetsysfsOnLinuxWhenGlobReturnsFalse()
function () {
echo "\n01-02-03-04-05-06\n";
},
'Linux'
'Linux',
'nothing disabled'
);

/*/ Act /*/
$provider = new SystemNodeProvider();
$node = $provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, ['/sys/class/net/*/address'], ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, ['/sys/class/net/*/address'], ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);

$this->assertEquals('010203040506', $node);
}
Expand All @@ -422,34 +437,67 @@ public function testCallGetsysfsOnLinuxWhenGlobReturnsEmptyArray()
function () {
echo "\n01-02-03-04-05-06\n";
},
'Linux'
'Linux',
'nothing disabled'
);

/*/ Act /*/
$provider = new SystemNodeProvider();
$node = $provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, ['/sys/class/net/*/address'], ['netstat -ie 2>&1'], [['a'], ['s']]);
$this->assertMockFunctions(null, ['/sys/class/net/*/address'], ['netstat -ie 2>&1'], [['a'], ['s']], ['disabled_functions']);

$this->assertEquals('010203040506', $node);
}

/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testGetNodeReturnsFalseWhenPassthruIsDisabled()
{
/*/ Arrange /*/
$this->arrangeMockFunctions(
null,
null,
null,
'NOT LINUX',
'PASSTHRU,some_other_function'
);

/*/ Act /*/
$provider = new SystemNodeProvider();
$node = $provider->getNode();

/*/ Assert /*/
$this->assertMockFunctions(null, null, null, [['s']], ['disabled_functions']);

$this->assertFalse($node);
}

/**
* Replaces the return value for functions with the given value or callback.
*
* @param callback|mixed|null $fileGetContentsBody
* @param callback|mixed|null $globBody
* @param callback|mixed|null $passthruBody
* @param callback|mixed|null $unameBody
* @param callback|mixed|null $iniGetDisableFunctionsBody
*/
private function arrangeMockFunctions($fileGetContentsBody, $globBody, $passthruBody, $unameBody)
{
private function arrangeMockFunctions(
$fileGetContentsBody,
$globBody,
$passthruBody,
$unameBody,
$iniGetDisableFunctionsBody
) {
$mockFunction = [
self::MOCK_FILE_GET_CONTENTS => $fileGetContentsBody,
self::MOCK_GLOB => $globBody,
self::MOCK_PASSTHRU => $passthruBody,
self::MOCK_UNAME => $unameBody,
self::MOCK_INI_GET => $iniGetDisableFunctionsBody,
];

array_walk($mockFunction, function ($body, $key) {
Expand All @@ -466,14 +514,21 @@ private function arrangeMockFunctions($fileGetContentsBody, $globBody, $passthru
* @param array|callable|null $globBodyAssert
* @param array|callable|null $passthruBodyAssert
* @param array|callable|null $unameBodyAssert
* @param array|callable|null $iniGetDisableFunctionsAssert
*/
private function assertMockFunctions($fileGetContentsAssert, $globBodyAssert, $passthruBodyAssert, $unameBodyAssert)
{
private function assertMockFunctions(
$fileGetContentsAssert,
$globBodyAssert,
$passthruBodyAssert,
$unameBodyAssert,
$iniGetDisableFunctionsAssert
) {
$mockFunctionAsserts = [
self::MOCK_FILE_GET_CONTENTS => $fileGetContentsAssert,
self::MOCK_GLOB => $globBodyAssert,
self::MOCK_PASSTHRU => $passthruBodyAssert,
self::MOCK_UNAME => $unameBodyAssert,
self::MOCK_INI_GET => $iniGetDisableFunctionsAssert,
];

array_walk($mockFunctionAsserts, function ($asserts, $key) {
Expand Down

0 comments on commit 8d62148

Please sign in to comment.