EncoderTest::testInvalidIpv6()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
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\ClassEnum;
16
use yswery\DNS\Encoder;
17
use yswery\DNS\Header;
18
use yswery\DNS\RdataEncoder;
19
use yswery\DNS\RecordTypeEnum;
20
use yswery\DNS\ResourceRecord;
21
22
class EncoderTest extends TestCase
23
{
24
    public function testEncodeDomainName()
25
    {
26
        $input_1 = 'www.example.com.';
27
        $expectation_1 = chr(3).'www'.chr(7).'example'.chr(3).'com'."\0";
28
29
        $input_2 = '.';
30
        $expectation_2 = "\0";
31
32
        $input_3 = 'tld.';
33
        $expectation_3 = chr(3).'tld'."\0";
34
35
        $this->assertEquals($expectation_1, Encoder::encodeDomainName($input_1));
36
        $this->assertEquals($expectation_2, Encoder::encodeDomainName($input_2));
37
        $this->assertEquals($expectation_3, Encoder::encodeDomainName($input_3));
38
    }
39
40
    /**
41
     * @throws \yswery\DNS\UnsupportedTypeException
42
     */
43
    public function testEncodeQuestionResourceRecord()
44
    {
45
        $input_1 = [];
46
        $input_1[] = (new ResourceRecord())
47
            ->setName('www.example.com.')
48
            ->setType(RecordTypeEnum::TYPE_A)
49
            ->setClass(ClassEnum::INTERNET)
50
            ->setQuestion(true);
51
52
        $expectation_1 =
53
            chr(3).'www'.chr(7).'example'.chr(3).'com'."\0".
54
            pack('nn', 1, 1);
55
56
        $input_2 = [];
57
        $input_2[] = (new ResourceRecord())
58
            ->setName('domain.com.au.')
59
            ->setType(RecordTypeEnum::TYPE_MX)
60
            ->setClass(ClassEnum::INTERNET)
61
            ->setQuestion(2);
0 ignored issues
show
Bug introduced by
2 of type integer is incompatible with the type boolean expected by parameter $question of yswery\DNS\ResourceRecord::setQuestion(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

61
            ->setQuestion(/** @scrutinizer ignore-type */ 2);
Loading history...
62
63
        $expectation_2 =
64
            chr(6).'domain'.chr(3).'com'.chr(2).'au'."\0".
65
            pack('nn', 15, 1);
66
67
        $input_3 = [$input_1[0], $input_2[0]];
68
        $expectation_3 = $expectation_1.$expectation_2;
69
70
        $this->assertEquals($expectation_1, Encoder::encodeResourceRecords($input_1));
71
        $this->assertEquals($expectation_2, Encoder::encodeResourceRecords($input_2));
72
        $this->assertEquals($expectation_3, Encoder::encodeResourceRecords($input_3));
73
    }
74
75
    /**
76
     * @throws \yswery\DNS\UnsupportedTypeException
77
     */
78
    public function testEncodeResourceRecord()
79
    {
80
        $name = 'example.com.';
81
        $nameEncoded = Encoder::encodeDomainName($name);
82
        $exchange = 'mail.example.com.';
83
        $exchangeEncoded = Encoder::encodeDomainName($exchange);
84
        $preference = 10;
85
        $ttl = 1337;
86
        $class = ClassEnum::INTERNET;
87
        $type = RecordTypeEnum::TYPE_MX;
88
        $ipAddress = '192.163.5.2';
89
90
        $rdata = pack('n', $preference).$exchangeEncoded;
91
        $rdata2 = inet_pton($ipAddress);
92
93
        $decoded1 = (new ResourceRecord())
94
            ->setName($name)
95
            ->setTtl($ttl)
96
            ->setType(RecordTypeEnum::TYPE_MX)
97
            ->setRdata([
98
                'preference' => $preference,
99
                'exchange' => $exchange,
100
            ]);
101
102
        $decoded2 = (new ResourceRecord())
103
            ->setName($name)
104
            ->setTtl($ttl)
105
            ->setType(RecordTypeEnum::TYPE_A)
106
            ->setRdata($ipAddress);
107
108
        $encoded1 = $nameEncoded.pack('nnNn', $type, $class, $ttl, strlen($rdata)).$rdata;
109
        $encoded2 = $nameEncoded.pack('nnNn', 1, $class, $ttl, strlen($rdata2)).$rdata2;
110
111
        $this->assertEquals($encoded1, Encoder::encodeResourceRecords([$decoded1]));
112
        $this->assertEquals($encoded2, Encoder::encodeResourceRecords([$decoded2]));
113
    }
114
115
    /**
116
     * @throws \yswery\DNS\UnsupportedTypeException
117
     */
118
    public function testEncodeType()
119
    {
120
        $decoded_1 = '192.168.0.1';
121
        $encoded_1 = inet_pton($decoded_1);
122
123
        $decoded_2 = '2001:acad:1337:b8::19';
124
        $encoded_2 = inet_pton($decoded_2);
125
126
        $decoded_5 = 'dns1.example.com.';
127
        $encoded_5 = chr(4).'dns1'.chr(7).'example'.chr(3).'com'."\0";
128
129
        $decoded_6 = [
130
            'mname' => 'example.com.',
131
            'rname' => 'postmaster.example.com',
132
            'serial' => 1970010188,
133
            'refresh' => 1800,
134
            'retry' => 7200,
135
            'expire' => 10800,
136
            'minimum' => 3600,
137
        ];
138
139
        $encoded_6 =
140
            chr(7).'example'.chr(3).'com'."\0".
141
            chr(10).'postmaster'.chr(7).'example'.chr(3).'com'."\0".
142
            pack('NNNNN', 1970010188, 1800, 7200, 10800, 3600);
143
144
        $decoded_7 = [
145
            'preference' => 15,
146
            'exchange' => 'mail.example.com.',
147
        ];
148
149
        $encoded_7 = pack('n', 15).chr(4).'mail'.chr(7).'example'.chr(3).'com'."\0";
150
151
        $decoded_8 = 'This is a comment.';
152
        $encoded_8 = chr(18).$decoded_8;
153
154
        $this->assertEquals($encoded_1, RdataEncoder::encodeRdata(1, $decoded_1));
155
        $this->assertEquals($encoded_2, RdataEncoder::encodeRdata(28, $decoded_2));
156
        $this->assertEquals($encoded_5, RdataEncoder::encodeRdata(2, $decoded_5));
157
        $this->assertEquals($encoded_6, RdataEncoder::encodeRdata(6, $decoded_6));
158
        $this->assertEquals($encoded_7, RdataEncoder::encodeRdata(15, $decoded_7));
159
        $this->assertEquals($encoded_8, RdataEncoder::encodeRdata(16, $decoded_8));
160
    }
161
162
    /**
163
     * @expectedException \InvalidArgumentException
164
     *
165
     * @throws \yswery\DNS\UnsupportedTypeException
166
     */
167
    public function testInvalidIpv4()
168
    {
169
        RdataEncoder::encodeRdata(RecordTypeEnum::TYPE_A, '192.168.1');
170
    }
171
172
    /**
173
     * @expectedException \InvalidArgumentException
174
     *
175
     * @throws \yswery\DNS\UnsupportedTypeException
176
     */
177
    public function testInvalidIpv6()
178
    {
179
        RdataEncoder::encodeRdata(RecordTypeEnum::TYPE_AAAA, '2001:acad:1337:b8:19');
180
    }
181
182
    public function testEncodeHeader()
183
    {
184
        $id = 1337;
185
        $flags = 0b1000010000000000;
186
        $qdcount = 1;
187
        $ancount = 2;
188
        $nscount = 0;
189
        $arcount = 0;
190
191
        $encoded = pack('nnnnnn', $id, $flags, $qdcount, $ancount, $nscount, $arcount);
192
193
        $header = new Header();
194
        $header
195
            ->setId($id)
196
            ->setResponse(true)
197
            ->setOpcode(Header::OPCODE_STANDARD_QUERY)
198
            ->setAuthoritative(true)
199
            ->setTruncated(false)
200
            ->setRecursionDesired(false)
201
            ->setRecursionAvailable(false)
202
            ->setRcode(Header::RCODE_NO_ERROR)
203
            ->setQuestionCount($qdcount)
204
            ->setAnswerCount($ancount)
205
            ->setNameServerCount($nscount)
206
            ->setAdditionalRecordsCount($arcount)
207
        ;
208
209
        $this->assertEquals($encoded, Encoder::encodeHeader($header));
210
    }
211
}
212