2620
2915
self.assertEqual(o.code, 1)
2621
2916
self.assertEqual(o.data, b'foobar')
2920
class RaisedArgs(Exception):
2922
An exception which can be raised by fakes to test that the fake is called
2923
with expected arguments.
2925
def __init__(self, args, kwargs):
2927
Store the positional and keyword arguments as attributes.
2929
@param args: The positional args.
2930
@param kwargs: The keyword args.
2933
self.kwargs = kwargs
2937
class MessageEmpty(object):
2939
Generate byte string and constructor arguments for an empty
2940
L{dns._EDNSMessage}.
2945
Bytes which are expected when encoding an instance constructed using
2946
C{kwargs} and which are expected to result in an identical instance when
2949
@return: The L{bytes} of a wire encoded message.
2952
b'\x01\x00' # id: 256
2953
b'\x97' # QR: 1, OPCODE: 2, AA: 0, TC: 0, RD: 1
2954
b'\x8f' # RA: 1, Z, RCODE: 15
2955
b'\x00\x00' # number of queries
2956
b'\x00\x00' # number of answers
2957
b'\x00\x00' # number of authorities
2958
b'\x00\x00' # number of additionals
2965
Keyword constructor arguments which are expected to result in an
2966
instance which returns C{bytes} when encoded.
2968
@return: A L{dict} of keyword arguments.
2973
opCode=dns.OP_STATUS,
2984
class MessageTruncated(object):
2986
An empty response message whose TR bit is set to 1.
2991
Bytes which are expected when encoding an instance constructed using
2992
C{kwargs} and which are expected to result in an identical instance when
2995
@return: The L{bytes} of a wire encoded message.
2998
b'\x01\x00' # ID: 256
2999
b'\x82' # QR: 1, OPCODE: 0, AA: 0, TC: 1, RD: 0
3000
b'\x00' # RA: 0, Z, RCODE: 0
3001
b'\x00\x00' # Number of queries
3002
b'\x00\x00' # Number of answers
3003
b'\x00\x00' # Number of authorities
3004
b'\x00\x00' # Number of additionals
3011
Keyword constructor arguments which are expected to result in an
3012
instance which returns C{bytes} when encoded.
3014
@return: A L{dict} of keyword arguments.
3029
class MessageNonAuthoritative(object):
3031
A minimal non-authoritative message.
3036
Bytes which are expected when encoding an instance constructed using
3037
C{kwargs} and which are expected to result in an identical instance when
3040
@return: The L{bytes} of a wire encoded message.
3043
b'\x01\x00' # ID 256
3044
b'\x00' # QR: 0, OPCODE: 0, AA: 0, TC: 0, RD: 0
3045
b'\x00' # RA: 0, Z, RCODE: 0
3046
b'\x00\x00' # Query count
3047
b'\x00\x01' # Answer count
3048
b'\x00\x00' # Authorities count
3049
b'\x00\x00' # Additionals count
3051
b'\x00' # RR NAME (root)
3052
b'\x00\x01' # RR TYPE 1 (A)
3053
b'\x00\x01' # RR CLASS 1 (IN)
3054
b'\x00\x00\x00\x00' # RR TTL
3055
b'\x00\x04' # RDLENGTH 4
3056
b'\x01\x02\x03\x04' # IPv4 1.2.3.4
3063
Keyword constructor arguments which are expected to result in an
3064
instance which returns C{bytes} when encoded.
3066
@return: A L{dict} of keyword arguments.
3075
payload=dns.Record_A('1.2.3.4', ttl=0),
3080
class MessageAuthoritative(object):
3082
A minimal authoritative message.
3087
Bytes which are expected when encoding an instance constructed using
3088
C{kwargs} and which are expected to result in an identical instance when
3091
@return: The L{bytes} of a wire encoded message.
3094
b'\x01\x00' # ID: 256
3095
b'\x04' # QR: 0, OPCODE: 0, AA: 1, TC: 0, RD: 0
3096
b'\x00' # RA: 0, Z, RCODE: 0
3097
b'\x00\x00' # Query count
3098
b'\x00\x01' # Answer count
3099
b'\x00\x00' # Authorities count
3100
b'\x00\x00' # Additionals count
3102
b'\x00' # RR NAME (root)
3103
b'\x00\x01' # RR TYPE 1 (A)
3104
b'\x00\x01' # RR CLASS 1 (IN)
3105
b'\x00\x00\x00\x00' # RR TTL
3106
b'\x00\x04' # RDLENGTH 4
3107
b'\x01\x02\x03\x04' # IPv4 1.2.3.4
3114
Keyword constructor arguments which are expected to result in an
3115
instance which returns C{bytes} when encoded.
3117
@return: A L{dict} of keyword arguments.
3126
payload=dns.Record_A('1.2.3.4', ttl=0),
3131
class MessageComplete:
3133
An example of a fully populated non-edns response message.
3135
Contains name compression, answers, authority, and additional records.
3140
Bytes which are expected when encoding an instance constructed using
3141
C{kwargs} and which are expected to result in an identical instance when
3144
@return: The L{bytes} of a wire encoded message.
3147
b'\x01\x00' # ID: 256
3148
b'\x95' # QR: 1, OPCODE: 2, AA: 1, TC: 0, RD: 1
3149
b'\x8f' # RA: 1, Z, RCODE: 15
3150
b'\x00\x01' # Query count
3151
b'\x00\x01' # Answer count
3152
b'\x00\x01' # Authorities count
3153
b'\x00\x01' # Additionals count
3155
# Query begins at Byte 12
3156
b'\x07example\x03com\x00' # QNAME
3157
b'\x00\x06' # QTYPE 6 (SOA)
3158
b'\x00\x01' # QCLASS 1 (IN)
3161
b'\xc0\x0c' # RR NAME (compression ref b12)
3162
b'\x00\x06' # RR TYPE 6 (SOA)
3163
b'\x00\x01' # RR CLASS 1 (IN)
3164
b'\xff\xff\xff\xff' # RR TTL
3165
b'\x00\x27' # RDLENGTH 39
3166
b'\x03ns1\xc0\x0c' # Mname (ns1.example.com (compression ref b15)
3167
b'\x0ahostmaster\xc0\x0c' # rname (hostmaster.example.com)
3168
b'\xff\xff\xff\xfe' # Serial
3169
b'\x7f\xff\xff\xfd' # Refresh
3170
b'\x7f\xff\xff\xfc' # Retry
3171
b'\x7f\xff\xff\xfb' # Expire
3172
b'\xff\xff\xff\xfa' # Minimum
3175
b'\xc0\x0c' # RR NAME (example.com compression ref b12)
3176
b'\x00\x02' # RR TYPE 2 (NS)
3177
b'\x00\x01' # RR CLASS 1 (IN)
3178
b'\xff\xff\xff\xff' # RR TTL
3179
b'\x00\x02' # RDLENGTH
3180
b'\xc0\x29' # RDATA (ns1.example.com (compression ref b41)
3183
b'\xc0\x29' # RR NAME (ns1.example.com compression ref b41)
3184
b'\x00\x01' # RR TYPE 1 (A)
3185
b'\x00\x01' # RR CLASS 1 (IN)
3186
b'\xff\xff\xff\xff' # RR TTL
3187
b'\x00\x04' # RDLENGTH
3188
b'\x05\x06\x07\x08' # RDATA 5.6.7.8
3195
Keyword constructor arguments which are expected to result in an
3196
instance which returns C{bytes} when encoded.
3198
@return: A L{dict} of keyword arguments.
3203
opCode=dns.OP_STATUS,
3209
queries=[dns.Query(b'example.com', dns.SOA)],
3216
payload=dns.Record_SOA(
3218
mname=b'ns1.example.com',
3219
rname=b'hostmaster.example.com',
3232
payload=dns.Record_NS(
3233
'ns1.example.com', ttl=0xffffffff))],
3240
payload=dns.Record_A(
3241
'5.6.7.8', ttl=0xffffffff))])
3245
class MessageEDNSQuery(object):
3247
A minimal EDNS query message.
3252
Bytes which are expected when encoding an instance constructed using
3253
C{kwargs} and which are expected to result in an identical instance when
3256
@return: The L{bytes} of a wire encoded message.
3260
b'\x00' # QR: 0, OPCODE: 0, AA: 0, TC: 0, RD: 0
3261
b'\x00' # RA: 0, Z, RCODE: 0
3262
b'\x00\x01' # Queries count
3263
b'\x00\x00' # Anwers count
3264
b'\x00\x00' # Authority count
3265
b'\x00\x01' # Additionals count
3268
b'\x03www\x07example\x03com\x00' # QNAME
3269
b'\x00\x01' # QTYPE (A)
3270
b'\x00\x01' # QCLASS (IN)
3272
# Additional OPT record
3274
b'\x00\x29' # TYPE (OPT 41)
3275
b'\x10\x00' # UDP Payload Size (4096)
3276
b'\x00' # Extended RCODE
3277
b'\x03' # EDNS version
3278
b'\x00\x00' # DO: False + Z
3279
b'\x00\x00' # RDLENGTH
3286
Keyword constructor arguments which are expected to result in an
3287
instance which returns C{bytes} when encoded.
3289
@return: A L{dict} of keyword arguments.
3294
opCode=dns.OP_QUERY,
3301
queries=[dns.Query(b'www.example.com', dns.A)],
3306
class MessageEDNSComplete(object):
3308
An example of a fully populated edns response message.
3310
Contains name compression, answers, authority, and additional records.
3315
Bytes which are expected when encoding an instance constructed using
3316
C{kwargs} and which are expected to result in an identical instance when
3319
@return: The L{bytes} of a wire encoded message.
3322
b'\x01\x00' # ID: 256
3323
b'\x95' # QR: 1, OPCODE: 2, AA: 1, TC: 0, RD: 1
3324
b'\xbf' # RA: 1, AD: 1, RCODE: 15
3325
b'\x00\x01' # Query count
3326
b'\x00\x01' # Answer count
3327
b'\x00\x01' # Authorities count
3328
b'\x00\x02' # Additionals count
3330
# Query begins at Byte 12
3331
b'\x07example\x03com\x00' # QNAME
3332
b'\x00\x06' # QTYPE 6 (SOA)
3333
b'\x00\x01' # QCLASS 1 (IN)
3336
b'\xc0\x0c' # RR NAME (compression ref b12)
3337
b'\x00\x06' # RR TYPE 6 (SOA)
3338
b'\x00\x01' # RR CLASS 1 (IN)
3339
b'\xff\xff\xff\xff' # RR TTL
3340
b'\x00\x27' # RDLENGTH 39
3341
b'\x03ns1\xc0\x0c' # mname (ns1.example.com (compression ref b15)
3342
b'\x0ahostmaster\xc0\x0c' # rname (hostmaster.example.com)
3343
b'\xff\xff\xff\xfe' # Serial
3344
b'\x7f\xff\xff\xfd' # Refresh
3345
b'\x7f\xff\xff\xfc' # Retry
3346
b'\x7f\xff\xff\xfb' # Expire
3347
b'\xff\xff\xff\xfa' # Minimum
3350
b'\xc0\x0c' # RR NAME (example.com compression ref b12)
3351
b'\x00\x02' # RR TYPE 2 (NS)
3352
b'\x00\x01' # RR CLASS 1 (IN)
3353
b'\xff\xff\xff\xff' # RR TTL
3354
b'\x00\x02' # RDLENGTH
3355
b'\xc0\x29' # RDATA (ns1.example.com (compression ref b41)
3358
b'\xc0\x29' # RR NAME (ns1.example.com compression ref b41)
3359
b'\x00\x01' # RR TYPE 1 (A)
3360
b'\x00\x01' # RR CLASS 1 (IN)
3361
b'\xff\xff\xff\xff' # RR TTL
3362
b'\x00\x04' # RDLENGTH
3363
b'\x05\x06\x07\x08' # RDATA 5.6.7.8
3365
# Additional OPT record
3367
b'\x00\x29' # TYPE (OPT 41)
3368
b'\x04\x00' # UDP Payload Size (1024)
3369
b'\x00' # Extended RCODE
3370
b'\x03' # EDNS version
3371
b'\x80\x00' # DO: True + Z
3372
b'\x00\x00' # RDLENGTH
3379
Keyword constructor arguments which are expected to result in an
3380
instance which returns C{bytes} when encoded.
3382
@return: A L{dict} of keyword arguments.
3387
opCode=dns.OP_STATUS,
3396
checkingDisabled=True,
3398
queries=[dns.Query(b'example.com', dns.SOA)],
3405
payload=dns.Record_SOA(
3407
mname=b'ns1.example.com',
3408
rname=b'hostmaster.example.com',
3421
payload=dns.Record_NS(
3422
'ns1.example.com', ttl=0xffffffff))],
3429
payload=dns.Record_A(
3430
'5.6.7.8', ttl=0xffffffff))])
3434
class MessageEDNSExtendedRCODE(object):
3436
An example of an EDNS message with an extended RCODE.
3441
Bytes which are expected when encoding an instance constructed using
3442
C{kwargs} and which are expected to result in an identical instance when
3445
@return: The L{bytes} of a wire encoded message.
3450
b'\x0c' # RA: 0, Z, RCODE: 12
3454
b'\x00\x01' # 1 additionals
3456
# Additional OPT record
3460
b'\xab' # Extended RCODE: 171
3470
Keyword constructor arguments which are expected to result in an
3471
instance which returns C{bytes} when encoded.
3473
@return: A L{dict} of keyword arguments.
3478
opCode=dns.OP_QUERY,
3483
rCode=0xabc, # Combined OPT extended RCODE + Message RCODE
3495
class MessageComparable(FancyEqMixin, FancyStrMixin, object):
3497
A wrapper around L{dns.Message} which is comparable so that it can be tested
3498
using some of the L{dns._EDNSMessage} tests.
3500
showAttributes = compareAttributes = (
3501
'id', 'answer', 'opCode', 'auth', 'trunc',
3502
'recDes', 'recAv', 'rCode',
3503
'queries', 'answers', 'authority', 'additional')
3505
def __init__(self, original):
3506
self.original = original
3509
def __getattr__(self, key):
3510
return getattr(self.original, key)
3514
def verifyConstructorArgument(testCase, cls, argName, defaultVal, altVal,
3517
Verify that an attribute has the expected default value and that a
3518
corresponding argument passed to a constructor is assigned to that
3521
@param testCase: The L{TestCase} whose assert methods will be
3523
@type testCase: L{unittest.TestCase}
3525
@param cls: The constructor under test.
3528
@param argName: The name of the constructor argument under test.
3529
@type argName: L{str}
3531
@param defaultVal: The expected default value of C{attrName} /
3533
@type defaultVal: L{object}
3535
@param altVal: A value which is different from the default. Used to
3536
test that supplied constructor arguments are actually assigned to the
3538
@type altVal: L{object}
3540
@param attrName: The name of the attribute under test if different
3541
from C{argName}. Defaults to C{argName}
3542
@type attrName: L{str}
3544
if attrName is None:
3548
expected = {'defaultVal': defaultVal, 'altVal': altVal}
3551
actual['defaultVal'] = getattr(o, attrName)
3553
o = cls(**{argName: altVal})
3554
actual['altVal'] = getattr(o, attrName)
3556
testCase.assertEqual(expected, actual)
3560
class ConstructorTestsMixin(object):
3562
Helper methods for verifying default attribute values and corresponding
3563
constructor arguments.
3565
def _verifyConstructorArgument(self, argName, defaultVal, altVal):
3567
Wrap L{verifyConstructorArgument} to provide simpler interface for
3568
testing Message and _EDNSMessage constructor arguments.
3570
@param argName: The name of the constructor argument.
3571
@param defaultVal: The expected default value.
3572
@param altVal: An alternative value which is expected to be assigned to
3573
a correspondingly named attribute.
3575
verifyConstructorArgument(testCase=self, cls=self.messageFactory,
3576
argName=argName, defaultVal=defaultVal,
3580
def _verifyConstructorFlag(self, argName, defaultVal):
3582
Wrap L{verifyConstructorArgument} to provide simpler interface for
3583
testing _EDNSMessage constructor flags.
3585
@param argName: The name of the constructor flag argument
3586
@param defaultVal: The expected default value of the flag
3588
assert defaultVal in (True, False)
3589
verifyConstructorArgument(testCase=self, cls=self.messageFactory,
3590
argName=argName, defaultVal=defaultVal,
3591
altVal=not defaultVal,)
3595
class CommonConstructorTestsMixin(object):
3597
Tests for constructor arguments and their associated attributes that are
3598
common to both L{twisted.names.dns._EDNSMessage} and L{dns.Message}.
3600
TestCase classes that use this mixin must provide a C{messageFactory} method
3601
which accepts any argment supported by L{dns.Message.__init__}.
3603
TestCases must also mixin ConstructorTestsMixin which provides some custom
3604
assertions for testing constructor arguments.
3608
L{dns._EDNSMessage.id} defaults to C{0} and can be overridden in
3611
self._verifyConstructorArgument('id', defaultVal=0, altVal=1)
3614
def test_answer(self):
3616
L{dns._EDNSMessage.answer} defaults to C{False} and can be overridden in
3619
self._verifyConstructorFlag('answer', defaultVal=False)
3622
def test_opCode(self):
3624
L{dns._EDNSMessage.opCode} defaults to L{dns.OP_QUERY} and can be
3625
overridden in the constructor.
3627
self._verifyConstructorArgument(
3628
'opCode', defaultVal=dns.OP_QUERY, altVal=dns.OP_STATUS)
3631
def test_auth(self):
3633
L{dns._EDNSMessage.auth} defaults to C{False} and can be overridden in
3636
self._verifyConstructorFlag('auth', defaultVal=False)
3639
def test_trunc(self):
3641
L{dns._EDNSMessage.trunc} defaults to C{False} and can be overridden in
3644
self._verifyConstructorFlag('trunc', defaultVal=False)
3647
def test_recDes(self):
3649
L{dns._EDNSMessage.recDes} defaults to C{False} and can be overridden in
3652
self._verifyConstructorFlag('recDes', defaultVal=False)
3655
def test_recAv(self):
3657
L{dns._EDNSMessage.recAv} defaults to C{False} and can be overridden in
3660
self._verifyConstructorFlag('recAv', defaultVal=False)
3663
def test_rCode(self):
3665
L{dns._EDNSMessage.rCode} defaults to C{0} and can be overridden in the
3668
self._verifyConstructorArgument('rCode', defaultVal=0, altVal=123)
3671
def test_maxSize(self):
3673
L{dns._EDNSMessage.maxSize} defaults to C{512} and can be overridden in
3676
self._verifyConstructorArgument('maxSize', defaultVal=512, altVal=1024)
3679
def test_queries(self):
3681
L{dns._EDNSMessage.queries} defaults to C{[]}.
3683
self.assertEqual(self.messageFactory().queries, [])
3686
def test_answers(self):
3688
L{dns._EDNSMessage.answers} defaults to C{[]}.
3690
self.assertEqual(self.messageFactory().answers, [])
3693
def test_authority(self):
3695
L{dns._EDNSMessage.authority} defaults to C{[]}.
3697
self.assertEqual(self.messageFactory().authority, [])
3700
def test_additional(self):
3702
L{dns._EDNSMessage.additional} defaults to C{[]}.
3704
self.assertEqual(self.messageFactory().additional, [])
3708
class EDNSMessageConstructorTests(ConstructorTestsMixin,
3709
CommonConstructorTestsMixin,
3710
unittest.SynchronousTestCase):
3712
Tests for L{twisted.names.dns._EDNSMessage} constructor arguments that are
3713
shared with L{dns.Message}.
3715
messageFactory = dns._EDNSMessage
3719
class MessageConstructorTests(ConstructorTestsMixin,
3720
CommonConstructorTestsMixin,
3721
unittest.SynchronousTestCase):
3723
Tests for L{twisted.names.dns.Message} constructor arguments that are shared
3724
with L{dns._EDNSMessage}.
3726
messageFactory = dns.Message
3730
class EDNSMessageSpecificsTestCase(ConstructorTestsMixin,
3731
unittest.SynchronousTestCase):
3733
Tests for L{dns._EDNSMessage}.
3735
These tests are for L{dns._EDNSMessage} APIs which are not shared with
3738
messageFactory = dns._EDNSMessage
3740
def test_ednsVersion(self):
3742
L{dns._EDNSMessage.ednsVersion} defaults to C{0} and can be overridden
3745
self._verifyConstructorArgument(
3746
'ednsVersion', defaultVal=0, altVal=None)
3749
def test_dnssecOK(self):
3751
L{dns._EDNSMessage.dnssecOK} defaults to C{False} and can be overridden
3754
self._verifyConstructorFlag('dnssecOK', defaultVal=False)
3757
def test_authenticData(self):
3759
L{dns._EDNSMessage.authenticData} defaults to C{False} and can be
3760
overridden in the constructor.
3762
self._verifyConstructorFlag('authenticData', defaultVal=False)
3765
def test_checkingDisabled(self):
3767
L{dns._EDNSMessage.checkingDisabled} defaults to C{False} and can be
3768
overridden in the constructor.
3770
self._verifyConstructorFlag('checkingDisabled', defaultVal=False)
3773
def test_queriesOverride(self):
3775
L{dns._EDNSMessage.queries} can be overridden in the constructor.
3777
msg = self.messageFactory(queries=[dns.Query(b'example.com')])
3781
[dns.Query(b'example.com')])
3784
def test_answersOverride(self):
3786
L{dns._EDNSMessage.answers} can be overridden in the constructor.
3788
msg = self.messageFactory(
3792
payload=dns.Record_A('1.2.3.4'))])
3796
[dns.RRHeader(b'example.com', payload=dns.Record_A('1.2.3.4'))])
3799
def test_authorityOverride(self):
3801
L{dns._EDNSMessage.authority} can be overridden in the constructor.
3803
msg = self.messageFactory(
3808
payload=dns.Record_SOA())])
3812
[dns.RRHeader(b'example.com', type=dns.SOA,
3813
payload=dns.Record_SOA())])
3816
def test_additionalOverride(self):
3818
L{dns._EDNSMessage.authority} can be overridden in the constructor.
3820
msg = self.messageFactory(
3824
payload=dns.Record_A('1.2.3.4'))])
3828
[dns.RRHeader(b'example.com', payload=dns.Record_A('1.2.3.4'))])
3831
def test_reprDefaults(self):
3833
L{dns._EDNSMessage.__repr__} omits field values and sections which are
3834
identical to their defaults. The id field value is always shown.
3837
'<_EDNSMessage id=0>',
3838
repr(self.messageFactory())
3842
def test_reprFlagsIfSet(self):
3844
L{dns._EDNSMessage.__repr__} displays flags if they are L{True}.
3846
m = self.messageFactory(answer=True, auth=True, trunc=True, recDes=True,
3847
recAv=True, authenticData=True,
3848
checkingDisabled=True, dnssecOK=True)
3852
'flags=answer,auth,trunc,recDes,recAv,authenticData,'
3853
'checkingDisabled,dnssecOK'
3859
def test_reprNonDefautFields(self):
3861
L{dns._EDNSMessage.__repr__} displays field values if they differ from
3864
m = self.messageFactory(id=10, opCode=20, rCode=30, maxSize=40,
3878
def test_reprNonDefaultSections(self):
3880
L{dns.Message.__repr__} displays sections which differ from their
3883
m = self.messageFactory()
3884
m.queries = [1, 2, 3]
3885
m.answers = [4, 5, 6]
3886
m.authority = [7, 8, 9]
3887
m.additional = [10, 11, 12]
3891
'queries=[1, 2, 3] '
3892
'answers=[4, 5, 6] '
3893
'authority=[7, 8, 9] '
3894
'additional=[10, 11, 12]'
3900
def test_fromStrCallsMessageFactory(self):
3902
L{dns._EDNSMessage.fromString} calls L{dns._EDNSMessage._messageFactory}
3903
to create a new L{dns.Message} instance which is used to decode the
3906
class FakeMessageFactory(object):
3908
Fake message factory.
3910
def fromStr(self, *args, **kwargs):
3912
Fake fromStr method which raises the arguments it was passed.
3914
@param args: positional arguments
3915
@param kwargs: keyword arguments
3917
raise RaisedArgs(args, kwargs)
3919
m = dns._EDNSMessage()
3920
m._messageFactory = FakeMessageFactory
3921
dummyBytes = object()
3922
e = self.assertRaises(RaisedArgs, m.fromStr, dummyBytes)
3924
((dummyBytes,), {}),
3929
def test_fromStrCallsFromMessage(self):
3931
L{dns._EDNSMessage.fromString} calls L{dns._EDNSMessage._fromMessage}
3932
with a L{dns.Message} instance
3934
m = dns._EDNSMessage()
3935
class FakeMessageFactory():
3937
Fake message factory.
3939
def fromStr(self, bytes):
3941
A noop fake version of fromStr
3943
@param bytes: the bytes to be decoded
3946
fakeMessage = FakeMessageFactory()
3947
m._messageFactory = lambda: fakeMessage
3949
def fakeFromMessage(*args, **kwargs):
3950
raise RaisedArgs(args, kwargs)
3951
m._fromMessage = fakeFromMessage
3952
e = self.assertRaises(RaisedArgs, m.fromStr, b'')
3954
((fakeMessage,), {}),
3959
def test_toStrCallsToMessage(self):
3961
L{dns._EDNSMessage.toStr} calls L{dns._EDNSMessage._toMessage}
3963
m = dns._EDNSMessage()
3964
def fakeToMessage(*args, **kwargs):
3965
raise RaisedArgs(args, kwargs)
3966
m._toMessage = fakeToMessage
3967
e = self.assertRaises(RaisedArgs, m.toStr)
3974
def test_toStrCallsToMessageToStr(self):
3976
L{dns._EDNSMessage.toStr} calls C{toStr} on the message returned by
3977
L{dns._EDNSMessage._toMessage}.
3979
m = dns._EDNSMessage()
3980
dummyBytes = object()
3981
class FakeMessage(object):
3987
Fake toStr which returns dummyBytes.
3993
def fakeToMessage(*args, **kwargs):
3994
return FakeMessage()
3995
m._toMessage = fakeToMessage
4004
class EDNSMessageEqualityTests(ComparisonTestsMixin, unittest.SynchronousTestCase):
4006
Tests for equality between L(dns._EDNSMessage} instances.
4008
These tests will not work with L{dns.Message} because it does not use
4009
L{twisted.python.util.FancyEqMixin}.
4012
messageFactory = dns._EDNSMessage
4016
Two L{dns._EDNSMessage} instances compare equal if they have the same
4019
self.assertNormalEqualityImplementation(
4020
self.messageFactory(id=1),
4021
self.messageFactory(id=1),
4022
self.messageFactory(id=2),
4026
def test_answer(self):
4028
Two L{dns._EDNSMessage} instances compare equal if they have the same
4031
self.assertNormalEqualityImplementation(
4032
self.messageFactory(answer=True),
4033
self.messageFactory(answer=True),
4034
self.messageFactory(answer=False),
4038
def test_opCode(self):
4040
Two L{dns._EDNSMessage} instances compare equal if they have the same
4043
self.assertNormalEqualityImplementation(
4044
self.messageFactory(opCode=dns.OP_STATUS),
4045
self.messageFactory(opCode=dns.OP_STATUS),
4046
self.messageFactory(opCode=dns.OP_INVERSE),
4050
def test_auth(self):
4052
Two L{dns._EDNSMessage} instances compare equal if they have the same
4055
self.assertNormalEqualityImplementation(
4056
self.messageFactory(auth=True),
4057
self.messageFactory(auth=True),
4058
self.messageFactory(auth=False),
4062
def test_trunc(self):
4064
Two L{dns._EDNSMessage} instances compare equal if they have the same
4067
self.assertNormalEqualityImplementation(
4068
self.messageFactory(trunc=True),
4069
self.messageFactory(trunc=True),
4070
self.messageFactory(trunc=False),
4074
def test_recDes(self):
4076
Two L{dns._EDNSMessage} instances compare equal if they have the same
4079
self.assertNormalEqualityImplementation(
4080
self.messageFactory(recDes=True),
4081
self.messageFactory(recDes=True),
4082
self.messageFactory(recDes=False),
4086
def test_recAv(self):
4088
Two L{dns._EDNSMessage} instances compare equal if they have the same
4091
self.assertNormalEqualityImplementation(
4092
self.messageFactory(recAv=True),
4093
self.messageFactory(recAv=True),
4094
self.messageFactory(recAv=False),
4098
def test_rCode(self):
4100
Two L{dns._EDNSMessage} instances compare equal if they have the same
4103
self.assertNormalEqualityImplementation(
4104
self.messageFactory(rCode=16),
4105
self.messageFactory(rCode=16),
4106
self.messageFactory(rCode=15),
4110
def test_ednsVersion(self):
4112
Two L{dns._EDNSMessage} instances compare equal if they have the same
4115
self.assertNormalEqualityImplementation(
4116
self.messageFactory(ednsVersion=1),
4117
self.messageFactory(ednsVersion=1),
4118
self.messageFactory(ednsVersion=None),
4122
def test_dnssecOK(self):
4124
Two L{dns._EDNSMessage} instances compare equal if they have the same
4127
self.assertNormalEqualityImplementation(
4128
self.messageFactory(dnssecOK=True),
4129
self.messageFactory(dnssecOK=True),
4130
self.messageFactory(dnssecOK=False),
4134
def test_authenticData(self):
4136
Two L{dns._EDNSMessage} instances compare equal if they have the same
4137
authenticData flags.
4139
self.assertNormalEqualityImplementation(
4140
self.messageFactory(authenticData=True),
4141
self.messageFactory(authenticData=True),
4142
self.messageFactory(authenticData=False),
4146
def test_checkingDisabled(self):
4148
Two L{dns._EDNSMessage} instances compare equal if they have the same
4149
checkingDisabled flags.
4151
self.assertNormalEqualityImplementation(
4152
self.messageFactory(checkingDisabled=True),
4153
self.messageFactory(checkingDisabled=True),
4154
self.messageFactory(checkingDisabled=False),
4158
def test_maxSize(self):
4160
Two L{dns._EDNSMessage} instances compare equal if they have the same
4163
self.assertNormalEqualityImplementation(
4164
self.messageFactory(maxSize=2048),
4165
self.messageFactory(maxSize=2048),
4166
self.messageFactory(maxSize=1024),
4170
def test_queries(self):
4172
Two L{dns._EDNSMessage} instances compare equal if they have the same
4175
self.assertNormalEqualityImplementation(
4176
self.messageFactory(queries=[dns.Query(b'example.com')]),
4177
self.messageFactory(queries=[dns.Query(b'example.com')]),
4178
self.messageFactory(queries=[dns.Query(b'example.org')]),
4182
def test_answers(self):
4184
Two L{dns._EDNSMessage} instances compare equal if they have the same
4187
self.assertNormalEqualityImplementation(
4188
self.messageFactory(answers=[dns.RRHeader(
4189
b'example.com', payload=dns.Record_A('1.2.3.4'))]),
4190
self.messageFactory(answers=[dns.RRHeader(
4191
b'example.com', payload=dns.Record_A('1.2.3.4'))]),
4192
self.messageFactory(answers=[dns.RRHeader(
4193
b'example.org', payload=dns.Record_A('4.3.2.1'))]),
4197
def test_authority(self):
4199
Two L{dns._EDNSMessage} instances compare equal if they have the same
4202
self.assertNormalEqualityImplementation(
4203
self.messageFactory(authority=[dns.RRHeader(
4205
type=dns.SOA, payload=dns.Record_SOA())]),
4206
self.messageFactory(authority=[dns.RRHeader(
4208
type=dns.SOA, payload=dns.Record_SOA())]),
4209
self.messageFactory(authority=[dns.RRHeader(
4211
type=dns.SOA, payload=dns.Record_SOA())]),
4215
def test_additional(self):
4217
Two L{dns._EDNSMessage} instances compare equal if they have the same
4220
self.assertNormalEqualityImplementation(
4221
self.messageFactory(additional=[dns.RRHeader(
4222
b'example.com', payload=dns.Record_A('1.2.3.4'))]),
4223
self.messageFactory(additional=[dns.RRHeader(
4224
b'example.com', payload=dns.Record_A('1.2.3.4'))]),
4225
self.messageFactory(additional=[dns.RRHeader(
4226
b'example.org', payload=dns.Record_A('1.2.3.4'))]),
4231
class StandardEncodingTestsMixin(object):
4233
Tests for the encoding and decoding of various standard (not EDNS) messages.
4235
These tests should work with both L{dns._EDNSMessage} and L{dns.Message}.
4237
TestCase classes that use this mixin must provide a C{messageFactory} method
4238
which accepts any argment supported by L{dns._EDNSMessage.__init__}.
4240
EDNS specific arguments may be discarded if not supported by the message
4241
class under construction.
4243
def test_emptyMessageEncode(self):
4245
An empty message can be encoded.
4248
self.messageFactory(**MessageEmpty.kwargs()).toStr(),
4249
MessageEmpty.bytes())
4252
def test_emptyMessageDecode(self):
4254
An empty message byte sequence can be decoded.
4256
m = self.messageFactory()
4257
m.fromStr(MessageEmpty.bytes())
4259
self.assertEqual(m, self.messageFactory(**MessageEmpty.kwargs()))
4262
def test_completeQueryEncode(self):
4264
A fully populated query message can be encoded.
4267
self.messageFactory(**MessageComplete.kwargs()).toStr(),
4268
MessageComplete.bytes())
4271
def test_completeQueryDecode(self):
4273
A fully populated message byte string can be decoded.
4275
m = self.messageFactory()
4276
m.fromStr(MessageComplete.bytes()),
4278
self.assertEqual(m, self.messageFactory(**MessageComplete.kwargs()))
4281
def test_NULL(self):
4283
A I{NULL} record with an arbitrary payload can be encoded and decoded as
4286
bytes = b''.join([dns._ord2bytes(i) for i in range(256)])
4287
rec = dns.Record_NULL(bytes)
4288
rr = dns.RRHeader(b'testname', dns.NULL, payload=rec)
4289
msg1 = self.messageFactory()
4290
msg1.answers.append(rr)
4293
msg2 = self.messageFactory()
4296
self.assertIsInstance(msg2.answers[0].payload, dns.Record_NULL)
4297
self.assertEqual(msg2.answers[0].payload.payload, bytes)
4300
def test_nonAuthoritativeMessageEncode(self):
4302
If the message C{authoritative} attribute is set to 0, the encoded bytes
4306
self.messageFactory(**MessageNonAuthoritative.kwargs()).toStr(),
4307
MessageNonAuthoritative.bytes())
4310
def test_nonAuthoritativeMessageDecode(self):
4312
The L{dns.RRHeader} instances created by a message from a
4313
non-authoritative message byte string are marked as not authoritative.
4315
m = self.messageFactory()
4316
m.fromStr(MessageNonAuthoritative.bytes())
4319
m, self.messageFactory(**MessageNonAuthoritative.kwargs()))
4322
def test_authoritativeMessageEncode(self):
4324
If the message C{authoritative} attribute is set to 1, the encoded bytes
4328
self.messageFactory(**MessageAuthoritative.kwargs()).toStr(),
4329
MessageAuthoritative.bytes())
4332
def test_authoritativeMessageDecode(self):
4334
The message and its L{dns.RRHeader} instances created by C{decode} from
4335
an authoritative message byte string, are marked as authoritative.
4337
m = self.messageFactory()
4338
m.fromStr(MessageAuthoritative.bytes())
4341
m, self.messageFactory(**MessageAuthoritative.kwargs()))
4344
def test_truncatedMessageEncode(self):
4346
If the message C{trunc} attribute is set to 1 the encoded bytes will
4350
self.messageFactory(**MessageTruncated.kwargs()).toStr(),
4351
MessageTruncated.bytes())
4354
def test_truncatedMessageDecode(self):
4356
The message instance created by decoding a truncated message is marked
4359
m = self.messageFactory()
4360
m.fromStr(MessageTruncated.bytes())
4362
self.assertEqual(m, self.messageFactory(**MessageTruncated.kwargs()))
4366
class EDNSMessageStandardEncodingTests(StandardEncodingTestsMixin,
4367
unittest.SynchronousTestCase):
4369
Tests for the encoding and decoding of various standard (non-EDNS) messages
4370
by L{dns._EDNSMessage}.
4372
messageFactory = dns._EDNSMessage
4376
class MessageStandardEncodingTests(StandardEncodingTestsMixin,
4377
unittest.SynchronousTestCase):
4379
Tests for the encoding and decoding of various standard (non-EDNS) messages
4383
def messageFactory(**kwargs):
4385
This function adapts constructor arguments expected by
4386
_EDNSMessage.__init__ to arguments suitable for use with the
4389
Also handles the fact that unlike L{dns._EDNSMessage},
4390
L{dns.Message.__init__} does not accept queries, answers etc as
4393
Also removes any L{dns._EDNSMessage} specific arguments.
4395
@param args: The positional arguments which will be passed to
4396
L{dns.Message.__init__}.
4398
@param kwargs: The keyword arguments which will be stripped of EDNS
4399
specific arguments before being passed to L{dns.Message.__init__}.
4401
@return: An L{dns.Message} instance.
4403
queries = kwargs.pop('queries', [])
4404
answers = kwargs.pop('answers', [])
4405
authority = kwargs.pop('authority', [])
4406
additional = kwargs.pop('additional', [])
4408
kwargs.pop('ednsVersion', None)
4410
m = dns.Message(**kwargs)
4413
m.authority = authority
4414
m.additional = additional
4415
return MessageComparable(m)
4419
class EDNSMessageEDNSEncodingTests(unittest.SynchronousTestCase):
4421
Tests for the encoding and decoding of various EDNS messages.
4423
These test will not work with L{dns.Message}.
4425
messageFactory = dns._EDNSMessage
4427
def test_ednsMessageDecodeStripsOptRecords(self):
4429
The L(_EDNSMessage} instance created by L{dns._EDNSMessage.decode} from
4430
an EDNS query never includes OPT records in the additional section.
4432
m = self.messageFactory()
4433
m.fromStr(MessageEDNSQuery.bytes())
4435
self.assertEqual(m.additional, [])
4438
def test_ednsMessageDecodeMultipleOptRecords(self):
4440
An L(_EDNSMessage} instance created from a byte string containing
4441
multiple I{OPT} records will discard all the C{OPT} records.
4443
C{ednsVersion} will be set to C{None}.
4445
@see: U{https://tools.ietf.org/html/rfc6891#section-6.1.1}
4449
dns._OPTHeader(version=2),
4450
dns._OPTHeader(version=3)]
4452
ednsMessage = dns._EDNSMessage()
4453
ednsMessage.fromStr(m.toStr())
4455
self.assertEqual(ednsMessage.ednsVersion, None)
4458
def test_fromMessageCopiesSections(self):
4460
L{dns._EDNSMessage._fromMessage} returns an L{_EDNSMessage} instance
4461
whose queries, answers, authority and additional lists are copies (not
4462
references to) the original message lists.
4464
standardMessage = dns.Message()
4465
standardMessage.fromStr(MessageEDNSQuery.bytes())
4467
ednsMessage = dns._EDNSMessage._fromMessage(standardMessage)
4470
for attrName in ('queries', 'answers', 'authority', 'additional'):
4471
if (getattr(standardMessage, attrName)
4472
is getattr(ednsMessage, attrName)):
4473
duplicates.append(attrName)
4477
'Message and _EDNSMessage shared references to the following '
4478
'section lists after decoding: %s' % (duplicates,))
4481
def test_toMessageCopiesSections(self):
4483
L{dns._EDNSMessage.toStr} makes no in place changes to the message
4486
ednsMessage = dns._EDNSMessage(ednsVersion=1)
4488
self.assertEqual(ednsMessage.additional, [])
4491
def test_optHeaderPosition(self):
4493
L{dns._EDNSMessage} can decode OPT records, regardless of their position
4494
in the additional records section.
4496
"The OPT RR MAY be placed anywhere within the additional data section."
4498
@see: U{https://tools.ietf.org/html/rfc6891#section-6.1.1}
4500
# XXX: We need an _OPTHeader.toRRHeader method. See #6779.
4502
optRecord = dns._OPTHeader(version=1)
4504
optRRHeader = dns.RRHeader()
4506
optRRHeader.decode(b)
4508
m.additional = [optRRHeader]
4511
actualMessages.append(dns._EDNSMessage._fromMessage(m).ednsVersion)
4513
m.additional.append(dns.RRHeader(type=dns.A))
4514
actualMessages.append(
4515
dns._EDNSMessage._fromMessage(m).ednsVersion)
4517
m.additional.insert(0, dns.RRHeader(type=dns.A))
4518
actualMessages.append(
4519
dns._EDNSMessage._fromMessage(m).ednsVersion)
4527
def test_ednsDecode(self):
4529
The L(_EDNSMessage} instance created by L{dns._EDNSMessage.fromStr}
4530
derives its edns specific values (C{ednsVersion}, etc) from the supplied
4533
m = self.messageFactory()
4534
m.fromStr(MessageEDNSComplete.bytes())
4536
self.assertEqual(m, self.messageFactory(**MessageEDNSComplete.kwargs()))
4539
def test_ednsEncode(self):
4541
The L(_EDNSMessage} instance created by L{dns._EDNSMessage.toStr}
4542
encodes its edns specific values (C{ednsVersion}, etc) into an OPT
4543
record added to the additional section.
4546
self.messageFactory(**MessageEDNSComplete.kwargs()).toStr(),
4547
MessageEDNSComplete.bytes())
4550
def test_extendedRcodeEncode(self):
4552
The L(_EDNSMessage.toStr} encodes the extended I{RCODE} (>=16) by
4553
assigning the lower 4bits to the message RCODE field and the upper 4bits
4554
to the OPT pseudo record.
4557
self.messageFactory(**MessageEDNSExtendedRCODE.kwargs()).toStr(),
4558
MessageEDNSExtendedRCODE.bytes())
4561
def test_extendedRcodeDecode(self):
4563
The L(_EDNSMessage} instance created by L{dns._EDNSMessage.fromStr}
4564
derives RCODE from the supplied OPT record.
4566
m = self.messageFactory()
4567
m.fromStr(MessageEDNSExtendedRCODE.bytes())
4570
m, self.messageFactory(**MessageEDNSExtendedRCODE.kwargs()))
4573
def test_extendedRcodeZero(self):
4575
Note that EXTENDED-RCODE value 0 indicates that an unextended RCODE is
4576
in use (values 0 through 15).
4578
https://tools.ietf.org/html/rfc6891#section-6.1.3
4580
ednsMessage = self.messageFactory(rCode=15, ednsVersion=0)
4581
standardMessage = ednsMessage._toMessage()
4585
(standardMessage.rCode, standardMessage.additional[0].extendedRCODE)
4590
class ResponseFromMessageTests(unittest.SynchronousTestCase):
4592
Tests for L{dns._responseFromMessage}.
4594
def test_responseFromMessageResponseType(self):
4596
L{dns.Message._responseFromMessage} is a constructor function which
4597
generates a new I{answer} message from an existing L{dns.Message} like
4600
request = dns.Message()
4601
response = dns._responseFromMessage(responseConstructor=dns.Message,
4603
self.assertIsNot(request, response)
4606
def test_responseType(self):
4608
L{dns._responseFromMessage} returns a new instance of C{cls}
4610
class SuppliedClass(object):
4614
expectedClass = dns.Message
4616
self.assertIsInstance(
4617
dns._responseFromMessage(responseConstructor=expectedClass,
4618
message=SuppliedClass()),
4623
def test_responseId(self):
4625
L{dns._responseFromMessage} copies the C{id} attribute of the original
4630
dns._responseFromMessage(responseConstructor=dns.Message,
4631
message=dns.Message(id=1234)).id
4635
def test_responseAnswer(self):
4637
L{dns._responseFromMessage} sets the C{answer} flag to L{True}
4639
request = dns.Message()
4640
response = dns._responseFromMessage(responseConstructor=dns.Message,
4644
(request.answer, response.answer)
4648
def test_responseQueries(self):
4650
L{dns._responseFromMessage} copies the C{queries} attribute of the
4653
request = dns.Message()
4654
expectedQueries = [object(), object(), object()]
4655
request.queries = expectedQueries[:]
4659
dns._responseFromMessage(responseConstructor=dns.Message,
4660
message=request).queries
4664
def test_responseKwargs(self):
4666
L{dns._responseFromMessage} accepts other C{kwargs} which are assigned
4667
to the new message before it is returned.
4671
dns._responseFromMessage(
4672
responseConstructor=dns.Message, message=dns.Message(),
4680
An example class for use in L{dns._compactRepr} tests.
4681
It follows the pattern of initialiser settable flags, fields and sections
4682
found in L{dns.Message} and L{dns._EDNSMessage}.
4685
field1=1, field2=2, alwaysShowField='AS',
4686
flagTrue=True, flagFalse=False, section1=None):
4688
Set some flags, fields and sections as public attributes.
4690
self.field1 = field1
4691
self.field2 = field2
4692
self.alwaysShowField = alwaysShowField
4693
self.flagTrue = flagTrue
4694
self.flagFalse = flagFalse
4696
if section1 is None:
4698
self.section1 = section1
4703
Call L{dns._compactRepr} to generate a string representation.
4705
return dns._compactRepr(
4707
alwaysShow='alwaysShowField'.split(),
4708
fieldNames='field1 field2 alwaysShowField'.split(),
4709
flagNames='flagTrue flagFalse'.split(),
4710
sectionNames='section1 section2'.split()
4715
class CompactReprTests(unittest.SynchronousTestCase):
4717
Tests for L[dns._compactRepr}.
4719
messageFactory = Foo
4720
def test_defaults(self):
4722
L{dns._compactRepr} omits field values and sections which have the
4723
default value. Flags which are True are always shown.
4726
"<Foo alwaysShowField='AS' flags=flagTrue>",
4727
repr(self.messageFactory())
4731
def test_flagsIfSet(self):
4733
L{dns._compactRepr} displays flags if they have a non-default value.
4735
m = self.messageFactory(flagTrue=True, flagFalse=True)
4738
"alwaysShowField='AS' "
4739
'flags=flagTrue,flagFalse'
4745
def test_nonDefautFields(self):
4747
L{dns._compactRepr} displays field values if they differ from their
4750
m = self.messageFactory(field1=10, field2=20)
4755
"alwaysShowField='AS' "
4762
def test_nonDefaultSections(self):
4764
L{dns._compactRepr} displays sections which differ from their defaults.
4766
m = self.messageFactory()
4767
m.section1 = [1, 1, 1]
4768
m.section2 = [2, 2, 2]
4771
"alwaysShowField='AS' "
4773
'section1=[1, 1, 1] '
4774
'section2=[2, 2, 2]'