@nictool/dns-resource-record 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codeclimate.yml +25 -0
- package/.github/FUNDING.yml +3 -0
- package/.github/workflows/ci.yml +43 -0
- package/.github/workflows/codeql.yml +14 -0
- package/.github/workflows/publish.yml +16 -0
- package/.gitmodules +3 -0
- package/CHANGELOG.md +18 -0
- package/DEVELOP.md +9 -0
- package/README.md +6 -2
- package/eslint.config.mjs +41 -0
- package/index.js +6 -0
- package/package.json +12 -3
- package/rr/a.js +13 -3
- package/rr/aaaa.js +14 -4
- package/rr/caa.js +25 -13
- package/rr/cname.js +3 -3
- package/rr/dname.js +4 -4
- package/rr/dnskey.js +6 -11
- package/rr/ds.js +6 -8
- package/rr/hinfo.js +8 -6
- package/rr/https.js +62 -0
- package/rr/ipseckey.js +20 -9
- package/rr/key.js +2 -2
- package/rr/loc.js +4 -4
- package/rr/mx.js +15 -3
- package/rr/naptr.js +2 -2
- package/rr/ns.js +1 -1
- package/rr/nsec.js +2 -4
- package/rr/nsec3.js +6 -12
- package/rr/nsec3param.js +4 -9
- package/rr/nxt.js +2 -4
- package/rr/openpgpkey.js +7 -3
- package/rr/rrsig.js +3 -4
- package/rr/sig.js +1 -1
- package/rr/smimea.js +3 -5
- package/rr/soa.js +1 -2
- package/rr/spf.js +1 -1
- package/rr/srv.js +4 -4
- package/rr/sshfp.js +1 -1
- package/rr/svcb.js +64 -0
- package/rr/tlsa.js +10 -10
- package/rr/tsig.js +10 -2
- package/rr/txt.js +5 -5
- package/rr/uri.js +2 -2
- package/rr/wks.js +4 -3
- package/rr.js +32 -20
- package/test/a.js +75 -0
- package/test/aaaa.js +86 -0
- package/test/base.js +148 -0
- package/test/caa.js +111 -0
- package/test/cert.js +48 -0
- package/test/cname.js +40 -0
- package/test/dname.js +57 -0
- package/test/dnskey.js +45 -0
- package/test/ds.js +45 -0
- package/test/fake.js +34 -0
- package/test/hinfo.js +80 -0
- package/test/https.js +56 -0
- package/test/ipseckey.js +141 -0
- package/test/key.js +36 -0
- package/test/loc.js +75 -0
- package/test/mx.js +78 -0
- package/test/naptr.js +47 -0
- package/test/ns.js +56 -0
- package/test/nsec.js +37 -0
- package/test/nsec3.js +47 -0
- package/test/nsec3param.js +23 -0
- package/test/nxt.js +37 -0
- package/test/openpgpkey.js +85 -0
- package/test/ptr.js +56 -0
- package/test/rr.js +212 -0
- package/test/smimea.js +51 -0
- package/test/soa.js +99 -0
- package/test/spf.js +51 -0
- package/test/srv.js +101 -0
- package/test/sshfp.js +69 -0
- package/test/svcb.js +56 -0
- package/test/tinydns.js +163 -0
- package/test/tlsa.js +63 -0
- package/test/txt.js +82 -0
- package/test/uri.js +65 -0
package/test/mx.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
|
|
3
|
+
import * as base from './base.js'
|
|
4
|
+
|
|
5
|
+
import MX from '../rr/mx.js'
|
|
6
|
+
|
|
7
|
+
const defaults = { class: 'IN', ttl: 3600, type: 'MX', preference: 0 }
|
|
8
|
+
|
|
9
|
+
const validRecords = [
|
|
10
|
+
{
|
|
11
|
+
...defaults,
|
|
12
|
+
owner: 'test.example.com.',
|
|
13
|
+
preference: 0,
|
|
14
|
+
exchange: 'mail.example.com.',
|
|
15
|
+
testB: 'test.example.com.\t3600\tIN\tMX\t0\tmail.example.com.\n',
|
|
16
|
+
testT: '@test.example.com::mail.example.com:0:3600::\n',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
...defaults,
|
|
20
|
+
owner: 'www.example.com.',
|
|
21
|
+
ttl: 86400,
|
|
22
|
+
preference: 0,
|
|
23
|
+
exchange: '.', // null MX, RFC 7505
|
|
24
|
+
testB: 'www.example.com.\t86400\tIN\tMX\t0\t.\n',
|
|
25
|
+
testT: '@www.example.com::.:0:86400::\n',
|
|
26
|
+
},
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
const invalidRecords = [
|
|
30
|
+
{
|
|
31
|
+
...defaults,
|
|
32
|
+
owner: 'test.example.com.',
|
|
33
|
+
exchange: 'not-full-qualified.example.com',
|
|
34
|
+
msg: /exchange must be fully qualified/,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
...defaults,
|
|
38
|
+
owner: 'test.example.com.',
|
|
39
|
+
exchange: '192.0.2.1',
|
|
40
|
+
msg: /exchange must be a FQDN/,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
...defaults,
|
|
44
|
+
owner: 'test.example.com.',
|
|
45
|
+
exchange: '-blah',
|
|
46
|
+
msg: /exchange must be fully qualified/,
|
|
47
|
+
},
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
describe('MX record', function () {
|
|
51
|
+
base.valid(MX, validRecords)
|
|
52
|
+
base.invalid(MX, invalidRecords)
|
|
53
|
+
|
|
54
|
+
base.getDescription(MX)
|
|
55
|
+
base.getRFCs(MX, validRecords[0])
|
|
56
|
+
base.getFields(MX, ['preference', 'exchange'])
|
|
57
|
+
base.getTypeId(MX, 15)
|
|
58
|
+
|
|
59
|
+
base.toBind(MX, validRecords)
|
|
60
|
+
base.toTinydns(MX, validRecords)
|
|
61
|
+
|
|
62
|
+
base.fromBind(MX, validRecords)
|
|
63
|
+
base.fromTinydns(MX, validRecords)
|
|
64
|
+
|
|
65
|
+
for (const val of validRecords) {
|
|
66
|
+
it.skip(`imports tinydns MX (@) record (${val.owner})`, async function () {
|
|
67
|
+
const r = new MX({ tinyline: val.testT })
|
|
68
|
+
if (process.env.DEBUG) console.dir(r)
|
|
69
|
+
for (const f of ['owner', 'exchange', 'preference', 'ttl']) {
|
|
70
|
+
assert.deepStrictEqual(
|
|
71
|
+
r.get(f),
|
|
72
|
+
val[f],
|
|
73
|
+
`${f}: ${r.get(f)} !== ${val[f]}`,
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
})
|
package/test/naptr.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as base from './base.js'
|
|
2
|
+
|
|
3
|
+
import NAPTR from '../rr/naptr.js'
|
|
4
|
+
|
|
5
|
+
const validRecords = [
|
|
6
|
+
{
|
|
7
|
+
owner: 'cid.urn.arpa.',
|
|
8
|
+
ttl: 86400,
|
|
9
|
+
class: 'IN',
|
|
10
|
+
type: 'NAPTR',
|
|
11
|
+
order: 100,
|
|
12
|
+
preference: 10,
|
|
13
|
+
flags: '',
|
|
14
|
+
service: '',
|
|
15
|
+
regexp: '!^urn:cid:.+@([^\\.]+\\.)(.*)$!\x02!i',
|
|
16
|
+
replacement: '.',
|
|
17
|
+
testB:
|
|
18
|
+
'cid.urn.arpa.\t86400\tIN\tNAPTR\t100\t10\t""\t""\t"!^urn:cid:.+@([^\\.]+\\.)(.*)$!\x02!i"\t.\n',
|
|
19
|
+
testT:
|
|
20
|
+
':cid.urn.arpa:35:\\000\\144\\000\\012\\000\\000\\040!^urn\\072cid\\072.+@([^\\134.]+\\134.)(.*)$!\x02!i\\001.\\000:86400::\n',
|
|
21
|
+
},
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
const invalidRecords = []
|
|
25
|
+
|
|
26
|
+
describe('NAPTR record', function () {
|
|
27
|
+
base.valid(NAPTR, validRecords)
|
|
28
|
+
base.invalid(NAPTR, invalidRecords)
|
|
29
|
+
|
|
30
|
+
base.getDescription(NAPTR)
|
|
31
|
+
base.getRFCs(NAPTR, validRecords[0])
|
|
32
|
+
base.getFields(NAPTR, [
|
|
33
|
+
'order',
|
|
34
|
+
'preference',
|
|
35
|
+
'flags',
|
|
36
|
+
'service',
|
|
37
|
+
'regexp',
|
|
38
|
+
'replacement',
|
|
39
|
+
])
|
|
40
|
+
base.getTypeId(NAPTR, 35)
|
|
41
|
+
|
|
42
|
+
base.toBind(NAPTR, validRecords)
|
|
43
|
+
base.toTinydns(NAPTR, validRecords)
|
|
44
|
+
|
|
45
|
+
base.fromBind(NAPTR, validRecords)
|
|
46
|
+
base.fromTinydns(NAPTR, validRecords)
|
|
47
|
+
})
|
package/test/ns.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
|
|
3
|
+
import * as base from './base.js'
|
|
4
|
+
|
|
5
|
+
import NS from '../rr/ns.js'
|
|
6
|
+
|
|
7
|
+
const defaults = { class: 'IN', ttl: 3600, type: 'NS' }
|
|
8
|
+
|
|
9
|
+
const validRecords = [
|
|
10
|
+
{
|
|
11
|
+
...defaults,
|
|
12
|
+
owner: 'example.com.',
|
|
13
|
+
dname: 'ns1.example.com.',
|
|
14
|
+
testB: 'example.com.\t3600\tIN\tNS\tns1.example.com.\n',
|
|
15
|
+
testT: '&example.com::ns1.example.com:3600::\n',
|
|
16
|
+
},
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
const invalidRecords = [
|
|
20
|
+
{
|
|
21
|
+
...defaults,
|
|
22
|
+
owner: 'example.com.',
|
|
23
|
+
dname: '1.2.3.4', // FQDN required
|
|
24
|
+
msg: /dname must be fully qualified/,
|
|
25
|
+
},
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
describe('NS record', function () {
|
|
29
|
+
base.valid(NS, validRecords)
|
|
30
|
+
base.invalid(NS, invalidRecords)
|
|
31
|
+
|
|
32
|
+
base.getDescription(NS)
|
|
33
|
+
base.getRFCs(NS, validRecords[0])
|
|
34
|
+
base.getFields(NS, ['dname'])
|
|
35
|
+
base.getTypeId(NS, 2)
|
|
36
|
+
|
|
37
|
+
base.toBind(NS, validRecords)
|
|
38
|
+
base.toTinydns(NS, validRecords)
|
|
39
|
+
|
|
40
|
+
base.fromBind(NS, validRecords)
|
|
41
|
+
base.fromTinydns(NS, validRecords)
|
|
42
|
+
|
|
43
|
+
for (const val of validRecords) {
|
|
44
|
+
it.skip(`imports tinydns NS (&) record (${val.owner})`, function () {
|
|
45
|
+
const r = new NS({ tinyline: val.testT })
|
|
46
|
+
if (process.env.DEBUG) console.dir(r)
|
|
47
|
+
for (const f of ['owner', 'dname', 'ttl']) {
|
|
48
|
+
assert.deepStrictEqual(
|
|
49
|
+
r.get(f),
|
|
50
|
+
val[f],
|
|
51
|
+
`${f}: ${r.get(f)} !== ${val[f]}`,
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
})
|
package/test/nsec.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as base from './base.js'
|
|
2
|
+
|
|
3
|
+
import NSEC from '../rr/nsec.js'
|
|
4
|
+
|
|
5
|
+
const validRecords = [
|
|
6
|
+
{
|
|
7
|
+
owner: 'alfa.example.com.',
|
|
8
|
+
ttl: 86400,
|
|
9
|
+
class: 'IN',
|
|
10
|
+
type: 'NSEC',
|
|
11
|
+
'next domain': 'host.example.com.',
|
|
12
|
+
'type bit maps': 'A MX RRSIG NSEC TYPE1234',
|
|
13
|
+
testB: `alfa.example.com.\t86400\tIN\tNSEC\thost.example.com.\tA MX RRSIG NSEC TYPE1234\n`,
|
|
14
|
+
// testT : '\n',
|
|
15
|
+
},
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
const invalidRecords = [
|
|
19
|
+
// {
|
|
20
|
+
// },
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
describe('NSEC record', function () {
|
|
24
|
+
base.valid(NSEC, validRecords)
|
|
25
|
+
base.invalid(NSEC, invalidRecords, { ttl: 3600 })
|
|
26
|
+
|
|
27
|
+
base.getDescription(NSEC)
|
|
28
|
+
base.getRFCs(NSEC, validRecords[0])
|
|
29
|
+
base.getFields(NSEC, ['next domain', 'type bit maps'])
|
|
30
|
+
base.getTypeId(NSEC, 47)
|
|
31
|
+
|
|
32
|
+
base.toBind(NSEC, validRecords)
|
|
33
|
+
// base.toTinydns(NSEC, validRecords)
|
|
34
|
+
|
|
35
|
+
base.fromBind(NSEC, validRecords)
|
|
36
|
+
// base.fromTinydns(NSEC, validRecords)
|
|
37
|
+
})
|
package/test/nsec3.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as base from './base.js'
|
|
2
|
+
|
|
3
|
+
import NSEC3 from '../rr/nsec3.js'
|
|
4
|
+
|
|
5
|
+
const defaults = { class: 'IN', ttl: 3600, type: 'NSEC3' }
|
|
6
|
+
|
|
7
|
+
const validRecords = [
|
|
8
|
+
{
|
|
9
|
+
...defaults,
|
|
10
|
+
owner: 'test.example.com.',
|
|
11
|
+
'hash algorithm': 1,
|
|
12
|
+
flags: 1,
|
|
13
|
+
iterations: 12,
|
|
14
|
+
salt: 'aabbccdd',
|
|
15
|
+
'type bit maps': 'A\tRRSIG',
|
|
16
|
+
'next hashed owner name': '2vptu5timamqttgl4luu9kg21e0aor3s',
|
|
17
|
+
testB:
|
|
18
|
+
'test.example.com.\t3600\tIN\tNSEC3\t1\t1\t12\taabbccdd\t(2vptu5timamqttgl4luu9kg21e0aor3s\tA\tRRSIG)\n',
|
|
19
|
+
testT:
|
|
20
|
+
':test.example.com:50:\\001\\001\\000\\014aabbccdd2vptu5timamqttgl4luu9kg21e0aor3sA\\011RRSIG:3600::\n',
|
|
21
|
+
},
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
const invalidRecords = []
|
|
25
|
+
|
|
26
|
+
describe('NSEC3 record', function () {
|
|
27
|
+
base.valid(NSEC3, validRecords)
|
|
28
|
+
base.invalid(NSEC3, invalidRecords, { ttl: 3600 })
|
|
29
|
+
|
|
30
|
+
base.getDescription(NSEC3)
|
|
31
|
+
base.getRFCs(NSEC3, validRecords[0])
|
|
32
|
+
base.getFields(NSEC3, [
|
|
33
|
+
'hash algorithm',
|
|
34
|
+
'flags',
|
|
35
|
+
'iterations',
|
|
36
|
+
'salt',
|
|
37
|
+
'next hashed owner name',
|
|
38
|
+
'type bit maps',
|
|
39
|
+
])
|
|
40
|
+
base.getTypeId(NSEC3, 50)
|
|
41
|
+
|
|
42
|
+
base.toBind(NSEC3, validRecords)
|
|
43
|
+
base.toTinydns(NSEC3, validRecords)
|
|
44
|
+
|
|
45
|
+
base.fromBind(NSEC3, validRecords)
|
|
46
|
+
// base.fromTinydns(NSEC3, validRecords)
|
|
47
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as base from './base.js'
|
|
2
|
+
|
|
3
|
+
import NSEC3PARAM from '../rr/nsec3param.js'
|
|
4
|
+
|
|
5
|
+
const validRecords = []
|
|
6
|
+
|
|
7
|
+
const invalidRecords = []
|
|
8
|
+
|
|
9
|
+
describe('NSEC3PARAM record', function () {
|
|
10
|
+
base.valid(NSEC3PARAM, validRecords)
|
|
11
|
+
base.invalid(NSEC3PARAM, invalidRecords, { ttl: 3600 })
|
|
12
|
+
|
|
13
|
+
base.getDescription(NSEC3PARAM)
|
|
14
|
+
base.getRFCs(NSEC3PARAM, validRecords[0])
|
|
15
|
+
base.getFields(NSEC3PARAM, ['hash algorithm', 'flags', 'iterations', 'salt'])
|
|
16
|
+
base.getTypeId(NSEC3PARAM, 51)
|
|
17
|
+
|
|
18
|
+
// base.toBind(NSEC3PARAM, validRecords)
|
|
19
|
+
// base.toTinydns(NSEC3PARAM, validRecords)
|
|
20
|
+
|
|
21
|
+
// base.fromBind(NSEC3PARAM, validRecords)
|
|
22
|
+
// base.fromTinydns(NSEC3PARAM, validRecords)
|
|
23
|
+
})
|
package/test/nxt.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as base from './base.js'
|
|
2
|
+
|
|
3
|
+
import NXT from '../rr/nxt.js'
|
|
4
|
+
|
|
5
|
+
const validRecords = [
|
|
6
|
+
{
|
|
7
|
+
owner: 'big.example.com.',
|
|
8
|
+
ttl: 86400,
|
|
9
|
+
class: 'IN',
|
|
10
|
+
type: 'NXT',
|
|
11
|
+
'next domain': 'medium.example.com.',
|
|
12
|
+
'type bit map': 'A SIG NXT',
|
|
13
|
+
testB: `big.example.com.\t86400\tIN\tNXT\tmedium.example.com.\tA SIG NXT\n`,
|
|
14
|
+
// testT : '\n',
|
|
15
|
+
},
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
const invalidRecords = [
|
|
19
|
+
// {
|
|
20
|
+
// },
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
describe('NXT record', function () {
|
|
24
|
+
base.valid(NXT, validRecords)
|
|
25
|
+
base.invalid(NXT, invalidRecords, { ttl: 3600 })
|
|
26
|
+
|
|
27
|
+
base.getDescription(NXT)
|
|
28
|
+
base.getRFCs(NXT, validRecords[0])
|
|
29
|
+
base.getFields(NXT, ['next domain', 'type bit map'])
|
|
30
|
+
base.getTypeId(NXT, 30)
|
|
31
|
+
|
|
32
|
+
base.toBind(NXT, validRecords)
|
|
33
|
+
// base.toTinydns(NXT, validRecords)
|
|
34
|
+
|
|
35
|
+
base.fromBind(NXT, validRecords)
|
|
36
|
+
// base.fromTinydns(NXT, validRecords)
|
|
37
|
+
})
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as base from './base.js'
|
|
2
|
+
|
|
3
|
+
import OPENPGPKEY from '../rr/openpgpkey.js'
|
|
4
|
+
|
|
5
|
+
const validRecords = [
|
|
6
|
+
{
|
|
7
|
+
owner: 'matt.example.com.',
|
|
8
|
+
ttl: 86400,
|
|
9
|
+
class: 'IN',
|
|
10
|
+
type: 'OPENPGPKEY',
|
|
11
|
+
'public key': `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
12
|
+
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
|
|
60
|
+
0VFBNRBmWIMXRAtmrzPyNp/nD7BymAQ=
|
|
61
|
+
=kezp
|
|
62
|
+
-----END PGP PUBLIC KEY BLOCK-----`,
|
|
63
|
+
testB:
|
|
64
|
+
'matt.example.com.\t86400\tIN\tOPENPGPKEY\t-----BEGIN PGP PUBLIC KEY BLOCK-----\n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\n0VFBNRBmWIMXRAtmrzPyNp/nD7BymAQ=\n=kezp\n-----END PGP PUBLIC KEY BLOCK-----\n',
|
|
65
|
+
// testT : '',
|
|
66
|
+
},
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
const invalidRecords = []
|
|
70
|
+
|
|
71
|
+
describe('OPENPGPKEY record', function () {
|
|
72
|
+
base.valid(OPENPGPKEY, validRecords)
|
|
73
|
+
base.invalid(OPENPGPKEY, invalidRecords, { ttl: 3600 })
|
|
74
|
+
|
|
75
|
+
base.getDescription(OPENPGPKEY)
|
|
76
|
+
base.getRFCs(OPENPGPKEY)
|
|
77
|
+
base.getFields(OPENPGPKEY, ['public key'])
|
|
78
|
+
base.getTypeId(OPENPGPKEY, 61)
|
|
79
|
+
|
|
80
|
+
base.toBind(OPENPGPKEY, validRecords)
|
|
81
|
+
// base.toTinydns(OPENPGPKEY, validRecords)
|
|
82
|
+
|
|
83
|
+
base.fromBind(OPENPGPKEY, validRecords)
|
|
84
|
+
// base.fromTinydns(OPENPGPKEY, validRecords)
|
|
85
|
+
})
|
package/test/ptr.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
|
|
3
|
+
import * as base from './base.js'
|
|
4
|
+
|
|
5
|
+
import PTR from '../rr/ptr.js'
|
|
6
|
+
|
|
7
|
+
const defaults = { class: 'IN', ttl: 86400, type: 'PTR' }
|
|
8
|
+
|
|
9
|
+
const validRecords = [
|
|
10
|
+
{
|
|
11
|
+
...defaults,
|
|
12
|
+
owner: '2.2.0.192.in-addr.arpa.',
|
|
13
|
+
dname: 'dhcp.example.com.',
|
|
14
|
+
testB: '2.2.0.192.in-addr.arpa.\t86400\tIN\tPTR\tdhcp.example.com.\n',
|
|
15
|
+
testT: '^2.2.0.192.in-addr.arpa:dhcp.example.com:86400::\n',
|
|
16
|
+
},
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
const invalidRecords = [
|
|
20
|
+
{
|
|
21
|
+
...defaults,
|
|
22
|
+
owner: 'example.com.',
|
|
23
|
+
dname: '192.0.2.4', // FQDN required
|
|
24
|
+
msg: /dname must be fully qualified/,
|
|
25
|
+
},
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
describe('PTR record', function () {
|
|
29
|
+
base.valid(PTR, validRecords)
|
|
30
|
+
base.invalid(PTR, invalidRecords)
|
|
31
|
+
|
|
32
|
+
base.getDescription(PTR)
|
|
33
|
+
base.getRFCs(PTR, validRecords[0])
|
|
34
|
+
base.getFields(PTR, ['dname'])
|
|
35
|
+
base.getTypeId(PTR, 12)
|
|
36
|
+
|
|
37
|
+
base.toBind(PTR, validRecords)
|
|
38
|
+
base.toTinydns(PTR, validRecords)
|
|
39
|
+
|
|
40
|
+
base.fromBind(PTR, validRecords)
|
|
41
|
+
base.fromTinydns(PTR, validRecords)
|
|
42
|
+
|
|
43
|
+
for (const val of validRecords) {
|
|
44
|
+
it.skip(`imports tinydns PTR (^) record (${val.owner})`, async function () {
|
|
45
|
+
const r = new PTR({ tinyline: val.testT })
|
|
46
|
+
if (process.env.DEBUG) console.dir(r)
|
|
47
|
+
for (const f of ['owner', 'dname', 'ttl']) {
|
|
48
|
+
assert.deepStrictEqual(
|
|
49
|
+
r.get(f),
|
|
50
|
+
val[f],
|
|
51
|
+
`${f}: ${r.get(f)} !== ${val[f]}`,
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
})
|
package/test/rr.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
|
|
3
|
+
import RR from '../rr.js'
|
|
4
|
+
import A from '../rr/a.js'
|
|
5
|
+
|
|
6
|
+
const cases = [
|
|
7
|
+
// { name: 'RR class', obj: RR, expect: [ 'owner', 'ttl', 'class', 'type' ] },
|
|
8
|
+
{
|
|
9
|
+
name: 'RR instance',
|
|
10
|
+
obj: new RR(null),
|
|
11
|
+
expect: ['owner', 'ttl', 'class', 'type'],
|
|
12
|
+
},
|
|
13
|
+
// { name: 'A class', obj: A, expect: [ 'owner', 'ttl', 'class', 'type', 'address' ] },
|
|
14
|
+
{
|
|
15
|
+
name: 'A instance',
|
|
16
|
+
obj: new A(null),
|
|
17
|
+
expect: ['owner', 'ttl', 'class', 'type', 'address'],
|
|
18
|
+
},
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
for (const c of cases) {
|
|
22
|
+
describe(`${c.name}`, function () {
|
|
23
|
+
describe('getFields', function () {
|
|
24
|
+
it('gets expected fields', async function () {
|
|
25
|
+
assert.deepStrictEqual(c.obj.getFields(), c.expect)
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
describe('RR', function () {
|
|
32
|
+
const r = new RR(null)
|
|
33
|
+
|
|
34
|
+
describe('setTtl', function () {
|
|
35
|
+
const invalid = [-1, -4, -299, 2147483648, undefined]
|
|
36
|
+
for (const i of invalid) {
|
|
37
|
+
it(`throws on invalid TTL: ${i}`, async function () {
|
|
38
|
+
try {
|
|
39
|
+
assert.deepStrictEqual(r.setTtl(i), false)
|
|
40
|
+
} catch (e) {
|
|
41
|
+
assert.ok(e.message)
|
|
42
|
+
console.error(e.message)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
describe('setClass', function () {
|
|
49
|
+
for (const i of ['IN', 'CH', 'ANY', 'NONE']) {
|
|
50
|
+
it(`accepts valid class: ${i}`, async function () {
|
|
51
|
+
r.setClass(i)
|
|
52
|
+
assert.deepEqual(r.get('class'), i)
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for (const i of ['matt', 'in', 0]) {
|
|
57
|
+
it(`throws on invalid class: ${i}`, async function () {
|
|
58
|
+
try {
|
|
59
|
+
assert.strictEqual(r.setClass(i), false)
|
|
60
|
+
} catch (e) {
|
|
61
|
+
assert.ok(e.message)
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
describe('fullyQualify', function () {
|
|
68
|
+
it('does nothing to empty hostname', async () => {
|
|
69
|
+
assert.equal(r.fullyQualify(''), '')
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('fully qualifies a valid hostname', async () => {
|
|
73
|
+
assert.equal(r.fullyQualify('example.com'), 'example.com.')
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
describe('getFQDN', function () {
|
|
78
|
+
it('adds a period to hostnames', async () => {
|
|
79
|
+
const rr = new RR(null)
|
|
80
|
+
rr.set('owner', 'www.example.com') // bypass FQ check
|
|
81
|
+
assert.equal(rr.getFQDN('owner'), 'www.example.com.')
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('reduces origin on request', async () => {
|
|
85
|
+
const rr = new RR(null)
|
|
86
|
+
const zone_opts = { origin: 'example.com.', hide: { origin: true } }
|
|
87
|
+
rr.setOwner('www.example.com.')
|
|
88
|
+
assert.equal(rr.getFQDN('owner', zone_opts), 'www')
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
describe('isFullyQualified', function () {
|
|
93
|
+
it('should detect FQDNs', async function () {
|
|
94
|
+
assert.deepEqual(
|
|
95
|
+
r.isFullyQualified('$type', '$field', 'host.example.com.'),
|
|
96
|
+
true,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
assert.deepEqual(
|
|
101
|
+
r.isFullyQualified('$type', '$field', 'host.example.com'),
|
|
102
|
+
false,
|
|
103
|
+
)
|
|
104
|
+
} catch (e) {
|
|
105
|
+
assert.ok(/must be fully qualified/.test(e.message))
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
describe('is8bitInt', function () {
|
|
111
|
+
const valid = [1, 2, 255]
|
|
112
|
+
const invalid = [-1, 'a', new Date(), undefined, 256]
|
|
113
|
+
|
|
114
|
+
for (const i of valid) {
|
|
115
|
+
it(`returns true for valid int: ${i}`, async function () {
|
|
116
|
+
assert.strictEqual(r.is8bitInt('test', 'field', i), true)
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
for (const i of invalid) {
|
|
121
|
+
it(`throws on invalid int: ${i}`, async function () {
|
|
122
|
+
try {
|
|
123
|
+
assert.strictEqual(r.is8bitInt('test', 'field', i), false)
|
|
124
|
+
} catch (e) {
|
|
125
|
+
assert.strictEqual(
|
|
126
|
+
e.message,
|
|
127
|
+
'test field must be a 8-bit integer (in the range 0-255)',
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
describe('is16bitInt', function () {
|
|
135
|
+
const valid = [0, 1, 2, 55555, 65535]
|
|
136
|
+
const invalid = ['a', new Date(), undefined, 65536]
|
|
137
|
+
|
|
138
|
+
for (const i of valid) {
|
|
139
|
+
it(`returns true for valid int: ${i}`, async function () {
|
|
140
|
+
assert.strictEqual(r.is16bitInt('test', 'field', i), true)
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
for (const i of invalid) {
|
|
145
|
+
it(`throws on invalid int: ${i}`, async function () {
|
|
146
|
+
try {
|
|
147
|
+
assert.strictEqual(r.is16bitInt('test', 'field', i), false)
|
|
148
|
+
} catch (e) {
|
|
149
|
+
assert.strictEqual(
|
|
150
|
+
e.message,
|
|
151
|
+
'test field must be a 16-bit integer (in the range 0-65535)',
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
describe('is32bitInt', function () {
|
|
159
|
+
const valid = [1, 2, 55555, 2147483647]
|
|
160
|
+
const invalid = ['a', new Date(), undefined, 2147483648]
|
|
161
|
+
|
|
162
|
+
for (const i of valid) {
|
|
163
|
+
it(`returns true for valid int: ${i}`, async function () {
|
|
164
|
+
assert.strictEqual(r.is32bitInt('test', 'field', i), true)
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
for (const i of invalid) {
|
|
169
|
+
it(`throws on invalid int: ${i}`, async function () {
|
|
170
|
+
try {
|
|
171
|
+
assert.strictEqual(r.is32bitInt('test', 'field', i), false)
|
|
172
|
+
} catch (e) {
|
|
173
|
+
assert.strictEqual(
|
|
174
|
+
e.message,
|
|
175
|
+
'test field must be a 32-bit integer (in the range 0-2147483647)',
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
describe('getQuoted', function () {
|
|
183
|
+
it('returns a quoted string', async () => {
|
|
184
|
+
r.set('cpu', '"already quoted"')
|
|
185
|
+
assert.equal(r.get('cpu'), '"already quoted"')
|
|
186
|
+
assert.equal(r.getQuoted('cpu'), '"already quoted"') // doesn't double quote
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
it("doesn't double quote a quoted string", async () => {
|
|
190
|
+
r.set('cpu', '"already quoted"')
|
|
191
|
+
assert.equal(r.getQuoted('cpu'), '"already quoted"')
|
|
192
|
+
})
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
describe('isQuoted', function () {
|
|
196
|
+
it('detects a quoted strings', async function () {
|
|
197
|
+
assert.deepEqual(r.isQuoted('"yes, this is"'), true)
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
it('detects non-quoted strings', async function () {
|
|
201
|
+
assert.deepEqual(r.isQuoted('nope, not quoted'), false)
|
|
202
|
+
})
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
describe('isValidHostname', function () {
|
|
206
|
+
for (const n of ['x', '2x', '*', '*.something']) {
|
|
207
|
+
it(`passes name: ${n}`, async function () {
|
|
208
|
+
assert.deepEqual(r.isValidHostname(n), true)
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
})
|
|
212
|
+
})
|