Passed
Push — master ( d7fd0c...0cd2cd )
by Sam
04:33
created

DecoderTest::testDecodeRdata()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 41
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

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