DecoderTest::testDecodeSrv()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 0
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of PHP DNS Server.
5
 *
6
 * (c) Yif Swery <[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 yswery\DNS\Tests;
13
14
use PHPUnit\Framework\TestCase;
15
use yswery\DNS\Decoder;
16
use yswery\DNS\Encoder;
17
use yswery\DNS\RdataDecoder;
18
use yswery\DNS\RdataEncoder;
19
use yswery\DNS\RecordTypeEnum;
20
use yswery\DNS\ResourceRecord;
21
22
class DecoderTest extends TestCase
23
{
24
    public function testDecodeDomainName()
25
    {
26
        $decoded_1 = 'www.example.com.';
27
        $encoded_1 = chr(3).'www'.chr(7).'example'.chr(3).'com'."\0";
28
29
        $decoded_2 = '.';
30
        $encoded_2 = "\0";
31
32
        $decoded_3 = 'tld.';
33
        $encoded_3 = chr(3).'tld'."\0";
34
35
        $offset = 0;
36
        $this->assertEquals($decoded_1, Decoder::decodeDomainName($encoded_1, $offset));
37
38
        $offset = 0;
39
        $this->assertEquals($decoded_2, Decoder::decodeDomainName($encoded_2, $offset));
40
41
        $offset = 0;
42
        $this->assertEquals($decoded_3, Decoder::decodeDomainName($encoded_3, $offset));
43
    }
44
45
    /**
46
     * @throws \yswery\DNS\UnsupportedTypeException
47
     */
48
    public function testDecodeQuestionResourceRecord()
49
    {
50
        $decoded_1[] = (new ResourceRecord())
0 ignored issues
show
Comprehensibility Best Practice introduced by
$decoded_1 was never initialized. Although not strictly required by PHP, it is generally a good practice to add $decoded_1 = array(); before regardless.
Loading history...
51
            ->setName('www.example.com.')
52
            ->setType(RecordTypeEnum::TYPE_A)
53
            ->setQuestion(true);
54
55
        $encoded_1 =
56
            chr(3).'www'.chr(7).'example'.chr(3).'com'."\0".
57
            pack('nn', 1, 1);
58
59
        $decoded_2[] = (new ResourceRecord())
0 ignored issues
show
Comprehensibility Best Practice introduced by
$decoded_2 was never initialized. Although not strictly required by PHP, it is generally a good practice to add $decoded_2 = array(); before regardless.
Loading history...
60
            ->setName('domain.com.au.')
61
            ->setType(RecordTypeEnum::TYPE_MX)
62
            ->setQuestion(true);
63
64
        $encoded_2 =
65
            chr(6).'domain'.chr(3).'com'.chr(2).'au'."\0".
66
            pack('nn', 15, 1);
67
68
        $decoded_3 = [$decoded_1[0], $decoded_2[0]];
69
        $encoded_3 = $encoded_1.$encoded_2;
70
71
        $offset = 0;
72
        $this->assertEquals($decoded_1, Decoder::decodeResourceRecords($encoded_1, 1, $offset, true));
73
        $offset = 0;
74
        $this->assertEquals($decoded_2, Decoder::decodeResourceRecords($encoded_2, 1, $offset, true));
75
        $offset = 0;
76
        $this->assertEquals($decoded_3, Decoder::decodeResourceRecords($encoded_3, 2, $offset, true));
77
    }
78
79
    /**
80
     * @throws \yswery\DNS\UnsupportedTypeException
81
     */
82
    public function testDecodeResourceRecords()
83
    {
84
        $name = 'example.com.';
85
        $nameEncoded = Encoder::encodeDomainName($name);
86
        $exchange = 'mail.example.com.';
87
        $exchangeEncoded = Encoder::encodeDomainName($exchange);
88
        $priority = 10;
89
        $ttl = 1337;
90
        $class = 1; //INTERNET
91
        $type = RecordTypeEnum::TYPE_MX;
92
        $ipAddress = '192.163.5.2';
93
94
        $rdata = pack('n', $priority).$exchangeEncoded;
95
        $rdata2 = inet_pton($ipAddress);
96
97
        $decoded1[] = (new ResourceRecord())
0 ignored issues
show
Comprehensibility Best Practice introduced by
$decoded1 was never initialized. Although not strictly required by PHP, it is generally a good practice to add $decoded1 = array(); before regardless.
Loading history...
98
            ->setName($name)
99
            ->setClass($class)
100
            ->setTtl($ttl)
101
            ->setType($type)
102
            ->setRdata([
103
                'preference' => $priority,
104
                'exchange' => $exchange,
105
            ]);
106
107
        $decoded2[] = (new ResourceRecord())
0 ignored issues
show
Comprehensibility Best Practice introduced by
$decoded2 was never initialized. Although not strictly required by PHP, it is generally a good practice to add $decoded2 = array(); before regardless.
Loading history...
108
            ->setName($name)
109
            ->setClass($class)
110
            ->setTtl($ttl)
111
            ->setType(RecordTypeEnum::TYPE_A)
112
            ->setRdata($ipAddress);
113
114
        $decoded3 = array_merge($decoded1, $decoded2);
115
116
        $encoded1 = $nameEncoded.pack('nnNn', $type, $class, $ttl, strlen($rdata)).$rdata;
117
        $encoded2 = $nameEncoded.pack('nnNn', 1, $class, $ttl, strlen($rdata2)).$rdata2;
118
        $encoded3 = $encoded1.$encoded2;
119
120
        $this->assertEquals($decoded1, Decoder::decodeResourceRecords($encoded1));
121
        $this->assertEquals($decoded2, Decoder::decodeResourceRecords($encoded2));
122
        $this->assertEquals($decoded3, Decoder::decodeResourceRecords($encoded3, 2));
123
    }
124
125
    /**
126
     * @throws \yswery\DNS\UnsupportedTypeException
127
     */
128
    public function testDecodeRdata()
129
    {
130
        $decoded_1 = '192.168.0.1';
131
        $encoded_1 = inet_pton($decoded_1);
132
133
        $decoded_2 = '2001:acad:1337:b8::19';
134
        $encoded_2 = inet_pton($decoded_2);
135
136
        $decoded_5 = 'dns1.example.com.';
137
        $encoded_5 = chr(4).'dns1'.chr(7).'example'.chr(3).'com'."\0";
138
139
        $decoded_6_prime = [
140
            'mname' => 'example.com.',
141
            'rname' => 'postmaster.example.com.',
142
            'serial' => 1970010188,
143
            'refresh' => 1800,
144
            'retry' => 7200,
145
            'expire' => 10800,
146
            'minimum' => 3600,
147
        ];
148
149
        $encoded_6 =
150
            chr(7).'example'.chr(3).'com'."\0".
151
            chr(10).'postmaster'.chr(7).'example'.chr(3).'com'."\0".
152
            pack('NNNNN', 1970010188, 1800, 7200, 10800, 3600);
153
154
        $encoded_7 = pack('n', 10).chr(4).'mail'.chr(7).'example'.chr(3).'com'."\0";
155
        $decoded_7_prime = [
156
            'preference' => 10,
157
            'exchange' => 'mail.example.com.',
158
        ];
159
160
        $decoded_8 = 'This is a comment.';
161
        $encoded_8 = chr(strlen($decoded_8)).$decoded_8;
162
163
        $this->assertEquals($decoded_1, RdataDecoder::decodeRdata(RecordTypeEnum::TYPE_A, $encoded_1));
164
        $this->assertEquals($decoded_2, RdataDecoder::decodeRdata(RecordTypeEnum::TYPE_AAAA, $encoded_2));
165
        $this->assertEquals($decoded_5, RdataDecoder::decodeRdata(RecordTypeEnum::TYPE_NS, $encoded_5));
166
        $this->assertEquals($decoded_6_prime, RdataDecoder::decodeRdata(RecordTypeEnum::TYPE_SOA, $encoded_6));
167
        $this->assertEquals($decoded_7_prime, RdataDecoder::decodeRdata(RecordTypeEnum::TYPE_MX, $encoded_7));
168
        $this->assertEquals($decoded_8, RdataDecoder::decodeRdata(RecordTypeEnum::TYPE_TXT, $encoded_8));
169
    }
170
171
    public function testDecodeHeader()
172
    {
173
        $id = 1337;
174
        $flags = 0b1000010000000000; //Indicates authoritative response.
175
        $qdcount = 1;
176
        $ancount = 2;
177
        $nscount = 0;
178
        $arcount = 0;
179
180
        $encoded = pack('nnnnnn', $id, $flags, $qdcount, $ancount, $nscount, $arcount);
181
        $header = Decoder::decodeHeader($encoded);
182
183
        $this->assertEquals($id, $header->getId());
184
        $this->assertEquals($qdcount, $header->getQuestionCount());
185
        $this->assertEquals($ancount, $header->getAnswerCount());
186
        $this->assertEquals($nscount, $header->getNameServerCount());
187
        $this->assertEquals($arcount, $header->getAdditionalRecordsCount());
188
189
        $this->assertTrue($header->isResponse());
190
        $this->assertEquals(0, $header->getOpcode());
191
        $this->assertTrue($header->isAuthoritative());
192
        $this->assertFalse($header->isTruncated());
193
        $this->assertFalse($header->isRecursionDesired());
194
        $this->assertFalse($header->isRecursionAvailable());
195
        $this->assertEquals(0, $header->getZ());
196
        $this->assertEquals(0, $header->getRcode());
197
    }
198
199
    /**
200
     * @throws \yswery\DNS\UnsupportedTypeException
201
     */
202
    public function testDecodeSrv()
203
    {
204
        $rdata = [
205
            'priority' => 1,
206
            'weight' => 5,
207
            'port' => 389,
208
            'target' => 'ldap.example.com.',
209
        ];
210
211
        $encoded = RdataEncoder::encodeRdata(RecordTypeEnum::TYPE_SRV, $rdata);
212
        $this->assertEquals($rdata, RdataDecoder::decodeRdata(RecordTypeEnum::TYPE_SRV, $encoded));
213
    }
214
}
215