Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8b1d91f

Browse files
committed
feature #18181 [PhpUnitBridge] Mock DNS functions (nicolas-grekas)
This PR was merged into the 3.1-dev branch. Discussion ---------- [PhpUnitBridge] Mock DNS functions | Q | A | ------------- | --- | Branch | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #16819 | License | MIT | Doc PR | - Commits ------- 0b31285 [PhpUnitBridge] Mock DNS functions
2 parents f29d46f + 0b31285 commit 8b1d91f

File tree

4 files changed

+415
-8
lines changed

4 files changed

+415
-8
lines changed

src/Symfony/Bridge/PhpUnit/ClockMock.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public static function register($class)
7474
$self = get_called_class();
7575

7676
$mockedNs = array(substr($class, 0, strrpos($class, '\\')));
77-
if (strpos($class, '\\Tests\\')) {
77+
if (0 < strpos($class, '\\Tests\\')) {
7878
$ns = str_replace('\\Tests\\', '\\', $class);
7979
$mockedNs[] = substr($ns, 0, strrpos($ns, '\\'));
8080
}
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\PhpUnit;
13+
14+
/**
15+
* @author Nicolas Grekas <[email protected]>
16+
*/
17+
class DnsMock
18+
{
19+
private static $hosts = array();
20+
private static $dnsTypes = array(
21+
'A' => DNS_A,
22+
'MX' => DNS_MX,
23+
'NS' => DNS_NS,
24+
'SOA' => DNS_SOA,
25+
'PTR' => DNS_PTR,
26+
'CNAME' => DNS_CNAME,
27+
'AAAA' => DNS_AAAA,
28+
'A6' => DNS_A6,
29+
'SRV' => DNS_SRV,
30+
'NAPTR' => DNS_NAPTR,
31+
'TXT' => DNS_TXT,
32+
'HINFO' => DNS_HINFO,
33+
);
34+
35+
/**
36+
* Configures the mock values for DNS queries.
37+
*
38+
* @param array $hosts Mocked hosts as keys, arrays of DNS records as returned by dns_get_record() as values.
39+
*/
40+
public static function withMockedHosts(array $hosts)
41+
{
42+
self::$hosts = $hosts;
43+
}
44+
45+
public static function checkdnsrr($hostname, $type = 'MX')
46+
{
47+
if (!self::$hosts) {
48+
return \checkdnsrr($hostname, $type);
49+
}
50+
if (isset(self::$hosts[$hostname])) {
51+
$type = strtoupper($type);
52+
53+
foreach (self::$hosts[$hostname] as $record) {
54+
if ($record['type'] === $type) {
55+
return true;
56+
}
57+
if ('ANY' === $type && isset(self::$dnsTypes[$record['type']]) && 'HINFO' !== $record['type']) {
58+
return true;
59+
}
60+
}
61+
}
62+
63+
return false;
64+
}
65+
66+
public static function getmxrr($hostname, &$mxhosts, &$weight = null)
67+
{
68+
if (!self::$hosts) {
69+
return \getmxrr($hostname, $mxhosts, $weight);
70+
}
71+
$mxhosts = $weight = array();
72+
73+
if (isset(self::$hosts[$hostname])) {
74+
foreach (self::$hosts[$hostname] as $record) {
75+
if ('MX' === $record['type']) {
76+
$mxhosts[] = $record['host'];
77+
$weight[] = $record['pri'];
78+
}
79+
}
80+
}
81+
82+
return (bool) $mxhosts;
83+
}
84+
85+
public static function gethostbyaddr($ipAddress)
86+
{
87+
if (!self::$hosts) {
88+
return \gethostbyaddr($ipAddress);
89+
}
90+
foreach (self::$hosts as $hostname => $records) {
91+
foreach ($records as $record) {
92+
if ('A' === $record['type'] && $ipAddress === $record['ip']) {
93+
return $hostname;
94+
}
95+
if ('AAAA' === $record['type'] && $ipAddress === $record['ipv6']) {
96+
return $hostname;
97+
}
98+
}
99+
}
100+
101+
return $ipAddress;
102+
}
103+
104+
public static function gethostbyname($hostname)
105+
{
106+
if (!self::$hosts) {
107+
return \gethostbyname($hostname);
108+
}
109+
if (isset(self::$hosts[$hostname])) {
110+
foreach (self::$hosts[$hostname] as $record) {
111+
if ('A' === $record['type']) {
112+
return $record['ip'];
113+
}
114+
}
115+
}
116+
117+
return $hostname;
118+
}
119+
120+
public static function gethostbynamel($hostname)
121+
{
122+
if (!self::$hosts) {
123+
return \gethostbynamel($hostname);
124+
}
125+
$ips = false;
126+
127+
if (isset(self::$hosts[$hostname])) {
128+
$ips = array();
129+
130+
foreach (self::$hosts[$hostname] as $record) {
131+
if ('A' === $record['type']) {
132+
$ips[] = $record['ip'];
133+
}
134+
}
135+
}
136+
137+
return $ips;
138+
}
139+
140+
public static function dns_get_record($hostname, $type = DNS_ANY, &$authns = null, &$addtl = null, $raw = false)
141+
{
142+
if (!self::$hosts) {
143+
return \dns_get_record($hostname, $type, $authns, $addtl, $raw);
144+
}
145+
146+
$records = false;
147+
148+
if (isset(self::$hosts[$hostname])) {
149+
if (DNS_ANY === $type) {
150+
$type = DNS_ALL;
151+
}
152+
$records = array();
153+
154+
foreach (self::$hosts[$hostname] as $record) {
155+
if (isset(self::$dnsTypes[$record['type']]) && (self::$dnsTypes[$record['type']] & $type)) {
156+
$records[] = array_merge(array('host' => $hostname, 'class' => 'IN', 'ttl' => 1, 'type' => $record['type']), $record);
157+
}
158+
}
159+
}
160+
161+
return $records;
162+
}
163+
164+
public static function register($class)
165+
{
166+
$self = get_called_class();
167+
168+
$mockedNs = array(substr($class, 0, strrpos($class, '\\')));
169+
if (0 < strpos($class, '\\Tests\\')) {
170+
$ns = str_replace('\\Tests\\', '\\', $class);
171+
$mockedNs[] = substr($ns, 0, strrpos($ns, '\\'));
172+
}
173+
foreach ($mockedNs as $ns) {
174+
if (function_exists($ns.'\checkdnsrr')) {
175+
continue;
176+
}
177+
eval(<<<EOPHP
178+
namespace $ns;
179+
180+
function checkdnsrr(\$host, \$type = 'MX')
181+
{
182+
return \\$self::checkdnsrr(\$host, \$type);
183+
}
184+
185+
function dns_check_record(\$host, \$type = 'MX')
186+
{
187+
return \\$self::checkdnsrr(\$host, \$type);
188+
}
189+
190+
function getmxrr(\$hostname, &\$mxhosts, &\$weight = null)
191+
{
192+
return \\$self::getmxrr(\$hostname, \$mxhosts, \$weight);
193+
}
194+
195+
function dns_get_mx(\$hostname, &\$mxhosts, &\$weight = null)
196+
{
197+
return \\$self::getmxrr(\$hostname, \$mxhosts, \$weight);
198+
}
199+
200+
function gethostbyaddr(\$ipAddress)
201+
{
202+
return \\$self::gethostbyaddr(\$ipAddress);
203+
}
204+
205+
function gethostbyname(\$hostname)
206+
{
207+
return \\$self::gethostbyname(\$hostname);
208+
}
209+
210+
function gethostbynamel(\$hostname)
211+
{
212+
return \\$self::gethostbynamel(\$hostname);
213+
}
214+
215+
function dns_get_record(\$hostname, \$type = DNS_ANY, &\$authns = null, &\$addtl = null, \$raw = false)
216+
{
217+
return \\$self::dns_get_record(\$hostname, \$type, \$authns, \$addtl, \$raw);
218+
}
219+
220+
EOPHP
221+
);
222+
}
223+
}
224+
}

src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,39 @@ class SymfonyTestsListener extends \PHPUnit_Framework_BaseTestListener
2626
private $wasSkipped = array();
2727
private $isSkipped = array();
2828

29-
public function __construct(array $extraClockMockedNamespaces = array())
29+
/**
30+
* @param array $mockedNamespaces List of namespaces, indexed by mocked features (time-sensitive or dns-sensitive).
31+
*/
32+
public function __construct(array $mockedNamespaces = array())
3033
{
31-
if ($extraClockMockedNamespaces) {
32-
foreach ($extraClockMockedNamespaces as $ns) {
33-
ClockMock::register($ns.'\DummyClass');
34+
$warn = false;
35+
foreach ($mockedNamespaces as $type => $namespaces) {
36+
if (!is_array($namespaces)) {
37+
$namespaces = array($namespaces);
38+
}
39+
if (is_int($type)) {
40+
// @deprecated BC with v2.8 to v3.0
41+
$type = 'time-sensitive';
42+
$warn = true;
43+
}
44+
if ('time-sensitive' === $type) {
45+
foreach ($namespaces as $ns) {
46+
ClockMock::register($ns.'\DummyClass');
47+
}
48+
}
49+
if ('dns-sensitive' === $type) {
50+
foreach ($namespaces as $ns) {
51+
DnsMock::register($ns.'\DummyClass');
52+
}
3453
}
3554
}
3655
if (self::$globallyEnabled) {
3756
$this->state = -2;
3857
} else {
3958
self::$globallyEnabled = true;
59+
if ($warn) {
60+
echo "Clock-mocked namespaces for SymfonyTestsListener need to be nested in a \"time-sensitive\" key. This will be enforced in Symfony 4.0.\n";
61+
}
4062
}
4163
}
4264

@@ -75,10 +97,16 @@ public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
7597
for ($i = 0; isset($testSuites[$i]); ++$i) {
7698
foreach ($testSuites[$i]->tests() as $test) {
7799
if ($test instanceof \PHPUnit_Framework_TestSuite) {
78-
if (class_exists($test->getName(), false) && in_array('time-sensitive', \PHPUnit_Util_Test::getGroups($test->getName()), true)) {
79-
ClockMock::register($test->getName());
80-
} else {
100+
if (!class_exists($test->getName(), false)) {
81101
$testSuites[] = $test;
102+
continue;
103+
}
104+
$groups = \PHPUnit_Util_Test::getGroups($test->getName());
105+
if (in_array('time-sensitive', $groups, true)) {
106+
ClockMock::register($test->getName());
107+
}
108+
if (in_array('dns-sensitive', $groups, true)) {
109+
DnsMock::register($test->getName());
82110
}
83111
}
84112
}
@@ -120,6 +148,9 @@ public function startTest(\PHPUnit_Framework_Test $test)
120148
ClockMock::register(get_class($test));
121149
ClockMock::withClockMock(true);
122150
}
151+
if (in_array('dns-sensitive', $groups, true)) {
152+
DnsMock::register(get_class($test));
153+
}
123154
}
124155
}
125156

@@ -131,6 +162,9 @@ public function endTest(\PHPUnit_Framework_Test $test, $time)
131162
if (in_array('time-sensitive', $groups, true)) {
132163
ClockMock::withClockMock(false);
133164
}
165+
if (in_array('dns-sensitive', $groups, true)) {
166+
DnsMock::withMockedHosts(array());
167+
}
134168
}
135169
}
136170
}

0 commit comments

Comments
 (0)