summaryrefslogtreecommitdiff
path: root/tests/test_svcb.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_svcb.py')
-rw-r--r--tests/test_svcb.py239
1 files changed, 239 insertions, 0 deletions
diff --git a/tests/test_svcb.py b/tests/test_svcb.py
new file mode 100644
index 0000000..d2f24b2
--- /dev/null
+++ b/tests/test_svcb.py
@@ -0,0 +1,239 @@
+import unittest
+
+import dns.rdata
+
+class SVCBTestCase(unittest.TestCase):
+ def check_valid_inputs(self, inputs):
+ expected = inputs[0]
+ for text in inputs:
+ rr = dns.rdata.from_text('IN', 'SVCB', text)
+ new_text = rr.to_text()
+ self.assertEqual(expected, new_text)
+
+ def check_invalid_inputs(self, inputs):
+ for text in inputs:
+ with self.assertRaises(dns.exception.SyntaxError):
+ dns.rdata.from_text('IN', 'SVCB', text)
+
+ def test_svcb_general_invalid(self):
+ invalid_inputs = (
+ # Duplicate keys
+ "1 . alpn=h2 alpn=h3",
+ "1 . alpn=h2 key1=h3",
+ # Quoted keys
+ "1 . \"alpn=h2\"",
+ # Invalid space
+ "1 . alpn= h2",
+ "1 . alpn =h2",
+ "1 . alpn = h2",
+ "1 . alpn= \"h2\"",
+ )
+ self.check_invalid_inputs(invalid_inputs)
+
+ def test_svcb_mandatory(self):
+ valid_inputs = (
+ "1 . mandatory=\"alpn,no-default-alpn\" alpn=\"h2\" no-default-alpn",
+ "1 . mandatory=alpn,no-default-alpn alpn=h2 no-default-alpn",
+ "1 . mandatory=key1,key2 alpn=h2 no-default-alpn",
+ "1 . mandatory=alpn,no-default-alpn key1=\\002h2 key2=\"\"",
+ "1 . mandatory=alpn,no-default-alpn key1=\\002h2 key2",
+ "1 . key0=\\000\\001\\000\\002 alpn=h2 no-default-alpn",
+ "1 . alpn=h2 no-default-alpn mandatory=alpn,no-default-alpn",
+ )
+ self.check_valid_inputs(valid_inputs)
+
+ invalid_inputs = (
+ # unknown key
+ "1 . mandatory=foo",
+ # key 0
+ "1 . mandatory=key0",
+ "1 . mandatory=key0,alpn",
+ # missing key
+ "1 . mandatory=alpn",
+ # duplicate
+ "1 . mandatory=alpn,alpn alpn=h2",
+ # invalid escaping
+ "1 . mandatory=\\alpn alpn=h2",
+ # 0 in wire format
+ "1 . key0=\\000\\000",
+ # invalid length in wire format
+ "1 . key0=\\000",
+ # out of order in wire format
+ "1 . key0=\\000\\002\\000\\001 alpn=h2 no-default-alpn",
+ # leading zeros
+ "1 . mandatory=key1,key002 alpn=h2 no-default-alpn",
+ )
+ self.check_invalid_inputs(invalid_inputs)
+
+ def test_svcb_alpn(self):
+ valid_inputs_two_items = (
+ "1 . alpn=\"h2,h3\"",
+ "1 . alpn=h2,h3",
+ "1 . alpn=h\\050,h3",
+ "1 . alpn=\"h\\050,h3\"",
+ "1 . alpn=\\h2,h3",
+ "1 . key1=\\002h2\\002h3",
+ )
+ self.check_valid_inputs(valid_inputs_two_items)
+
+ valid_inputs_one_item = (
+ "1 . alpn=\"h2\\,h3\"",
+ "1 . alpn=h2\\,h3",
+ "1 . alpn=h2\\044h3",
+ )
+ self.check_valid_inputs(valid_inputs_one_item)
+
+ invalid_inputs = (
+ "1 . alpn=h2,,h3",
+ "1 . alpn=01234567890abcdef01234567890abcdef01234567890abcdef"
+ "01234567890abcdef01234567890abcdef01234567890abcdef"
+ "01234567890abcdef01234567890abcdef01234567890abcdef"
+ "01234567890abcdef01234567890abcdef01234567890abcdef"
+ "01234567890abcdef01234567890abcdef01234567890abcdef"
+ "01234567890abcdef",
+ "1 . key1=\\000",
+ "1 . key1=\\002x",
+ "1 . alpn=\",h2,h3\"",
+ "1 . alpn=\"h2,h3,\"",
+ "1 . alpn",
+ )
+ self.check_invalid_inputs(invalid_inputs)
+
+ def test_svcb_no_default_alpn(self):
+ valid_inputs = (
+ "1 . no-default-alpn",
+ "1 . no-default-alpn=\"\"",
+ "1 . key2",
+ "1 . key2=\"\"",
+ )
+ self.check_valid_inputs(valid_inputs)
+
+ invalid_inputs = (
+ "1 . no-default-alpn=foo",
+ "1 . no-default-alpn=",
+ "1 . key2=foo",
+ "1 . key2=",
+ )
+ self.check_invalid_inputs(invalid_inputs)
+
+ def test_svcb_port(self):
+ valid_inputs = (
+ "1 . port=\"53\"",
+ "1 . port=53",
+ "1 . key3=\\000\\053",
+ )
+ self.check_valid_inputs(valid_inputs)
+
+ invalid_inputs = (
+ "1 . port=",
+ "1 . port=53x",
+ "1 . port=x53",
+ "1 . port=53,54",
+ "1 . port=53\\,54",
+ "1 . key3=\\000",
+ )
+ self.check_invalid_inputs(invalid_inputs)
+
+ def test_svcb_echconfig(self):
+ valid_inputs = (
+ "1 . echconfig=\"Zm9vMA==\"",
+ "1 . echconfig=Zm9vMA==",
+ "1 . key5=foo0",
+ "1 . key5=\\102\\111\\111\\048",
+ )
+ self.check_valid_inputs(valid_inputs)
+
+ invalid_inputs = (
+ "1 . echconfig=",
+ "1 . echconfig=Zm9vMA",
+ "1 . key5=",
+ )
+ self.check_invalid_inputs(invalid_inputs)
+
+ def test_svcb_ipv4hint(self):
+ valid_inputs = (
+ "1 . ipv4hint=\"0.0.0.0,1.1.1.1\"",
+ "1 . ipv4hint=0.0.0.0,1.1.1.1",
+ "1 . key4=\\000\\000\\000\\000\\001\\001\\001\\001",
+ )
+ self.check_valid_inputs(valid_inputs)
+
+ invalid_inputs = (
+ "1 . ipv4hint=",
+ "1 . ipv4hint=1234",
+ "1 . ipv4hint=1\\.2.3.4",
+ "1 . ipv4hint=1.2.3.4\\,2.3.4.5",
+ "1 . ipv4hint",
+ "1 . key4=",
+ "1 . key4=123",
+ )
+ self.check_invalid_inputs(invalid_inputs)
+
+ def test_svcb_ipv6hint(self):
+ valid_inputs = (
+ "1 . ipv6hint=\"::4,1::\"",
+ "1 . ipv6hint=::4,1::",
+ "1 . key6=\\000\\000\\000\\000\\000\\000\\000\\000"
+ "\\000\\000\\000\\000\\000\\000\\000\\004"
+ "\\000\\001\\000\\000\\000\\000\\000\\000"
+ "\\000\\000\\000\\000\\000\\000\\000\\000",
+ )
+ self.check_valid_inputs(valid_inputs)
+
+ invalid_inputs = (
+ "1 . ipv6hint=",
+ "1 . ipv6hint=1234",
+ "1 . ipv6hint=1\\::2",
+ "1 . ipv6hint=::1\\,::2",
+ "1 . ipv6hint",
+ "1 . key6=",
+ "1 . key6=123",
+ )
+ self.check_invalid_inputs(invalid_inputs)
+
+ def test_svcb_unknown(self):
+ valid_inputs_one_key = (
+ "1 . key23=\"key45\"",
+ "1 . key23=key45",
+ "1 . key23=key\\052\\053",
+ "1 . key23=\"key\\052\\053\"",
+ "1 . key23=\\107\\101\\121\\052\\053",
+ )
+ self.check_valid_inputs(valid_inputs_one_key)
+
+ valid_inputs_two_keys = (
+ "1 . key24 key48",
+ "1 . key24=\"\" key48",
+ )
+ self.check_valid_inputs(valid_inputs_two_keys)
+
+ invalid_inputs = (
+ "1 . key65536=foo",
+ "1 . key24= key48",
+ )
+ self.check_invalid_inputs(invalid_inputs)
+
+ def test_svcb_wire(self):
+ valid_inputs = (
+ "1 . mandatory=\"alpn,port\" alpn=\"h2\" port=\"257\"",
+ "\\# 24 0001 00 0000000400010003 00010003026832 000300020101",
+ )
+ self.check_valid_inputs(valid_inputs)
+
+ everything = \
+ "100 foo.com. mandatory=\"alpn,port\" alpn=\"h2,h3\" " \
+ " no-default-alpn port=\"12345\" echconfig=\"abcd\" " \
+ " ipv4hint=1.2.3.4,4.3.2.1 ipv6hint=1::2,3::4" \
+ " key12345=\"foo\""
+ rr = dns.rdata.from_text('IN', 'SVCB', everything)
+ rr2 = dns.rdata.from_text('IN', 'SVCB', rr.to_generic().to_text())
+ self.assertEqual(rr, rr2)
+
+ invalid_inputs = (
+ # As above, but the keys are out of order.
+ "\\# 24 0001 00 0000000400010003 000300020101 00010003026832",
+ # As above, but the mandatory keys don't match
+ "\\# 24 0001 00 0000000400010002 000300020101 00010003026832",
+ "\\# 24 0001 00 0000000400010004 000300020101 00010003026832",
+ )
+ self.check_invalid_inputs(invalid_inputs)