~landscape/twisted/14.0.2-1ubuntu1

« back to all changes in this revision

Viewing changes to twisted/names/test/test_dns.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-07-14 13:53:15 UTC
  • mfrom: (1.3.2) (44.2.3 sid)
  • Revision ID: package-import@ubuntu.com-20140714135315-z2f6727ypy31nldq
Tags: 14.0.0-1ubuntu1
* Merge with Debian; remaining changes:
  - Keep the preliminary python3 support, but don't enable it.
  - Try to use plain pygtkcompat and fall back to gi.pygtkcompat, to
    avoid a DeprecationWarning, and a crash.
  - Use new io_add_watch api on new versions of pygobject.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
from zope.interface.verify import verifyClass
16
16
 
17
17
from twisted.python.failure import Failure
 
18
from twisted.python.util import FancyEqMixin, FancyStrMixin
18
19
from twisted.internet import address, task
19
20
from twisted.internet.error import CannotListenError, ConnectionDone
20
21
from twisted.trial import unittest
55
56
        When passed a non-string object, L{dns.str2name} returns it unmodified.
56
57
        """
57
58
        time = object()
58
 
        self.assertIdentical(time, dns.str2time(time))
 
59
        self.assertIs(time, dns.str2time(time))
59
60
 
60
61
 
61
62
    def test_seconds(self):
675
676
        self.assertEqual(m.checkingDisabled, 1)
676
677
 
677
678
 
 
679
    def test_reprDefaults(self):
 
680
        """
 
681
        L{dns.Message.__repr__} omits field values and sections which are
 
682
        identical to their defaults. The id field value is always shown.
 
683
        """
 
684
        self.assertEqual(
 
685
            '<Message id=0>',
 
686
            repr(dns.Message())
 
687
        )
 
688
 
 
689
 
 
690
    def test_reprFlagsIfSet(self):
 
691
        """
 
692
        L{dns.Message.__repr__} displays flags if they are L{True}.
 
693
        """
 
694
        m = dns.Message(answer=True, auth=True, trunc=True, recDes=True,
 
695
                        recAv=True, authenticData=True, checkingDisabled=True)
 
696
        self.assertEqual(
 
697
            '<Message '
 
698
            'id=0 '
 
699
            'flags=answer,auth,trunc,recDes,recAv,authenticData,'
 
700
            'checkingDisabled'
 
701
            '>',
 
702
            repr(m),
 
703
        )
 
704
 
 
705
 
 
706
    def test_reprNonDefautFields(self):
 
707
        """
 
708
        L{dns.Message.__repr__} displays field values if they differ from their
 
709
        defaults.
 
710
        """
 
711
        m = dns.Message(id=10, opCode=20, rCode=30, maxSize=40)
 
712
        self.assertEqual(
 
713
            '<Message '
 
714
            'id=10 '
 
715
            'opCode=20 '
 
716
            'rCode=30 '
 
717
            'maxSize=40'
 
718
            '>',
 
719
            repr(m),
 
720
        )
 
721
 
 
722
 
 
723
    def test_reprNonDefaultSections(self):
 
724
        """
 
725
        L{dns.Message.__repr__} displays sections which differ from their
 
726
        defaults.
 
727
        """
 
728
        m = dns.Message()
 
729
        m.queries = [1, 2, 3]
 
730
        m.answers = [4, 5, 6]
 
731
        m.authority = [7, 8, 9]
 
732
        m.additional = [10, 11, 12]
 
733
        self.assertEqual(
 
734
            '<Message '
 
735
            'id=0 '
 
736
            'queries=[1, 2, 3] '
 
737
            'answers=[4, 5, 6] '
 
738
            'authority=[7, 8, 9] '
 
739
            'additional=[10, 11, 12]'
 
740
            '>',
 
741
            repr(m),
 
742
        )
 
743
 
 
744
 
678
745
    def testEmptyMessage(self):
679
746
        """
680
747
        Test that a message which has been truncated causes an EOFError to
701
768
            b'\x00\x00' # number of additionals
702
769
            )
703
770
        self.assertEqual(msg.id, 256)
704
 
        self.failIf(msg.answer, "Message was not supposed to be an answer.")
 
771
        self.assertFalse(
 
772
            msg.answer, "Message was not supposed to be an answer.")
705
773
        self.assertEqual(msg.opCode, dns.OP_QUERY)
706
 
        self.failIf(msg.auth, "Message was not supposed to be authoritative.")
707
 
        self.failIf(msg.trunc, "Message was not supposed to be truncated.")
 
774
        self.assertFalse(
 
775
            msg.auth, "Message was not supposed to be authoritative.")
 
776
        self.assertFalse(
 
777
            msg.trunc, "Message was not supposed to be truncated.")
708
778
        self.assertEqual(msg.queries, [])
709
779
        self.assertEqual(msg.answers, [])
710
780
        self.assertEqual(msg.authority, [])
727
797
        msg2 = dns.Message()
728
798
        msg2.decode(s)
729
799
 
730
 
        self.failUnless(isinstance(msg2.answers[0].payload, dns.Record_NULL))
 
800
        self.assertIsInstance(msg2.answers[0].payload, dns.Record_NULL)
731
801
        self.assertEqual(msg2.answers[0].payload.payload, bytes)
732
802
 
733
803
 
740
810
        # 65280 is the first value in the range reserved for private
741
811
        # use, so it shouldn't ever conflict with an officially
742
812
        # allocated value.
743
 
        self.assertIdentical(
744
 
            dns.Message().lookupRecordType(65280), dns.UnknownRecord)
 
813
        self.assertIs(dns.Message().lookupRecordType(65280), dns.UnknownRecord)
745
814
 
746
815
 
747
816
    def test_nonAuthoritativeMessage(self):
798
867
 
799
868
 
800
869
 
 
870
class MessageComparisonTests(ComparisonTestsMixin,
 
871
                             unittest.SynchronousTestCase):
 
872
    """
 
873
    Tests for the rich comparison of L{dns.Message} instances.
 
874
    """
 
875
    def messageFactory(self, *args, **kwargs):
 
876
        """
 
877
        Create a L{dns.Message}.
 
878
 
 
879
        The L{dns.Message} constructor doesn't accept C{queries}, C{answers},
 
880
        C{authority}, C{additional} arguments, so we extract them from the
 
881
        kwargs supplied to this factory function and assign them to the message.
 
882
 
 
883
        @param args: Positional arguments.
 
884
        @param kwargs: Keyword arguments.
 
885
        @return: A L{dns.Message} instance.
 
886
        """
 
887
        queries = kwargs.pop('queries', [])
 
888
        answers = kwargs.pop('answers', [])
 
889
        authority = kwargs.pop('authority', [])
 
890
        additional = kwargs.pop('additional', [])
 
891
        m = dns.Message(**kwargs)
 
892
        if queries:
 
893
            m.queries = queries
 
894
        if answers:
 
895
            m.answers = answers
 
896
        if authority:
 
897
            m.authority = authority
 
898
        if additional:
 
899
            m.additional = additional
 
900
        return m
 
901
 
 
902
 
 
903
    def test_id(self):
 
904
        """
 
905
        Two L{dns.Message} instances compare equal if they have the same id
 
906
        value.
 
907
        """
 
908
        self.assertNormalEqualityImplementation(
 
909
            self.messageFactory(id=10),
 
910
            self.messageFactory(id=10),
 
911
            self.messageFactory(id=20),
 
912
        )
 
913
 
 
914
 
 
915
    def test_answer(self):
 
916
        """
 
917
        Two L{dns.Message} instances compare equal if they have the same answer
 
918
        flag.
 
919
        """
 
920
        self.assertNormalEqualityImplementation(
 
921
            self.messageFactory(answer=1),
 
922
            self.messageFactory(answer=1),
 
923
            self.messageFactory(answer=0),
 
924
        )
 
925
 
 
926
 
 
927
    def test_opCode(self):
 
928
        """
 
929
        Two L{dns.Message} instances compare equal if they have the same opCode
 
930
        value.
 
931
        """
 
932
        self.assertNormalEqualityImplementation(
 
933
            self.messageFactory(opCode=10),
 
934
            self.messageFactory(opCode=10),
 
935
            self.messageFactory(opCode=20),
 
936
        )
 
937
 
 
938
 
 
939
    def test_recDes(self):
 
940
        """
 
941
        Two L{dns.Message} instances compare equal if they have the same recDes
 
942
        flag.
 
943
        """
 
944
        self.assertNormalEqualityImplementation(
 
945
            self.messageFactory(recDes=1),
 
946
            self.messageFactory(recDes=1),
 
947
            self.messageFactory(recDes=0),
 
948
        )
 
949
 
 
950
 
 
951
    def test_recAv(self):
 
952
        """
 
953
        Two L{dns.Message} instances compare equal if they have the same recAv
 
954
        flag.
 
955
        """
 
956
        self.assertNormalEqualityImplementation(
 
957
            self.messageFactory(recAv=1),
 
958
            self.messageFactory(recAv=1),
 
959
            self.messageFactory(recAv=0),
 
960
        )
 
961
 
 
962
 
 
963
    def test_auth(self):
 
964
        """
 
965
        Two L{dns.Message} instances compare equal if they have the same auth
 
966
        flag.
 
967
        """
 
968
        self.assertNormalEqualityImplementation(
 
969
            self.messageFactory(auth=1),
 
970
            self.messageFactory(auth=1),
 
971
            self.messageFactory(auth=0),
 
972
        )
 
973
 
 
974
 
 
975
    def test_rCode(self):
 
976
        """
 
977
        Two L{dns.Message} instances compare equal if they have the same rCode
 
978
        value.
 
979
        """
 
980
        self.assertNormalEqualityImplementation(
 
981
            self.messageFactory(rCode=10),
 
982
            self.messageFactory(rCode=10),
 
983
            self.messageFactory(rCode=20),
 
984
        )
 
985
 
 
986
 
 
987
    def test_trunc(self):
 
988
        """
 
989
        Two L{dns.Message} instances compare equal if they have the same trunc
 
990
        flag.
 
991
        """
 
992
        self.assertNormalEqualityImplementation(
 
993
            self.messageFactory(trunc=1),
 
994
            self.messageFactory(trunc=1),
 
995
            self.messageFactory(trunc=0),
 
996
        )
 
997
 
 
998
 
 
999
    def test_maxSize(self):
 
1000
        """
 
1001
        Two L{dns.Message} instances compare equal if they have the same
 
1002
        maxSize value.
 
1003
        """
 
1004
        self.assertNormalEqualityImplementation(
 
1005
            self.messageFactory(maxSize=10),
 
1006
            self.messageFactory(maxSize=10),
 
1007
            self.messageFactory(maxSize=20),
 
1008
        )
 
1009
 
 
1010
 
 
1011
    def test_authenticData(self):
 
1012
        """
 
1013
        Two L{dns.Message} instances compare equal if they have the same
 
1014
        authenticData flag.
 
1015
        """
 
1016
        self.assertNormalEqualityImplementation(
 
1017
            self.messageFactory(authenticData=1),
 
1018
            self.messageFactory(authenticData=1),
 
1019
            self.messageFactory(authenticData=0),
 
1020
        )
 
1021
 
 
1022
 
 
1023
    def test_checkingDisabled(self):
 
1024
        """
 
1025
        Two L{dns.Message} instances compare equal if they have the same
 
1026
        checkingDisabled flag.
 
1027
        """
 
1028
        self.assertNormalEqualityImplementation(
 
1029
            self.messageFactory(checkingDisabled=1),
 
1030
            self.messageFactory(checkingDisabled=1),
 
1031
            self.messageFactory(checkingDisabled=0),
 
1032
        )
 
1033
 
 
1034
 
 
1035
    def test_queries(self):
 
1036
        """
 
1037
        Two L{dns.Message} instances compare equal if they have the same
 
1038
        queries.
 
1039
        """
 
1040
        self.assertNormalEqualityImplementation(
 
1041
            self.messageFactory(queries=[dns.Query(b'example.com')]),
 
1042
            self.messageFactory(queries=[dns.Query(b'example.com')]),
 
1043
            self.messageFactory(queries=[dns.Query(b'example.org')]),
 
1044
            )
 
1045
 
 
1046
 
 
1047
    def test_answers(self):
 
1048
        """
 
1049
        Two L{dns.Message} instances compare equal if they have the same
 
1050
        answers.
 
1051
        """
 
1052
        self.assertNormalEqualityImplementation(
 
1053
            self.messageFactory(answers=[dns.RRHeader(
 
1054
                        b'example.com', payload=dns.Record_A('1.2.3.4'))]),
 
1055
            self.messageFactory(answers=[dns.RRHeader(
 
1056
                        b'example.com', payload=dns.Record_A('1.2.3.4'))]),
 
1057
            self.messageFactory(answers=[dns.RRHeader(
 
1058
                        b'example.org', payload=dns.Record_A('4.3.2.1'))]),
 
1059
            )
 
1060
 
 
1061
 
 
1062
    def test_authority(self):
 
1063
        """
 
1064
        Two L{dns.Message} instances compare equal if they have the same
 
1065
        authority records.
 
1066
        """
 
1067
        self.assertNormalEqualityImplementation(
 
1068
            self.messageFactory(authority=[dns.RRHeader(
 
1069
                        b'example.com',
 
1070
                        type=dns.SOA, payload=dns.Record_SOA())]),
 
1071
            self.messageFactory(authority=[dns.RRHeader(
 
1072
                        b'example.com',
 
1073
                        type=dns.SOA, payload=dns.Record_SOA())]),
 
1074
            self.messageFactory(authority=[dns.RRHeader(
 
1075
                        b'example.org',
 
1076
                        type=dns.SOA, payload=dns.Record_SOA())]),
 
1077
            )
 
1078
 
 
1079
 
 
1080
    def test_additional(self):
 
1081
        """
 
1082
        Two L{dns.Message} instances compare equal if they have the same
 
1083
        additional records.
 
1084
        """
 
1085
        self.assertNormalEqualityImplementation(
 
1086
            self.messageFactory(additional=[dns.RRHeader(
 
1087
                        b'example.com', payload=dns.Record_A('1.2.3.4'))]),
 
1088
            self.messageFactory(additional=[dns.RRHeader(
 
1089
                        b'example.com', payload=dns.Record_A('1.2.3.4'))]),
 
1090
            self.messageFactory(additional=[dns.RRHeader(
 
1091
                        b'example.org', payload=dns.Record_A('1.2.3.4'))]),
 
1092
            )
 
1093
 
 
1094
 
 
1095
 
801
1096
class TestController(object):
802
1097
    """
803
1098
    Pretend to be a DNS query processor for a DNSDatagramProtocol.
2144
2439
            udpPayloadSize=512,
2145
2440
            extendedRCODE=3,
2146
2441
            version=4,
2147
 
            dnssecOK=1)
 
2442
            dnssecOK=True)
2148
2443
 
2149
2444
 
2150
2445
 
2458
2753
            udpPayloadSize=0xffff,
2459
2754
            extendedRCODE=0xfe,
2460
2755
            version=0xfd,
2461
 
            dnssecOK=1,
 
2756
            dnssecOK=True,
2462
2757
            options=[dns._OPTVariableOption(code=0xffff, data=b'abc')])
2463
2758
 
2464
2759
        self.assertEqual(decodedOptHeader, expectedOptHeader)
2520
2815
        dnssecOK flags.
2521
2816
        """
2522
2817
        self.assertNormalEqualityImplementation(
2523
 
            dns._OPTHeader(dnssecOK=1),
2524
 
            dns._OPTHeader(dnssecOK=1),
2525
 
            dns._OPTHeader(dnssecOK=0))
 
2818
            dns._OPTHeader(dnssecOK=True),
 
2819
            dns._OPTHeader(dnssecOK=True),
 
2820
            dns._OPTHeader(dnssecOK=False))
2526
2821
 
2527
2822
 
2528
2823
    def test_equalityOptions(self):
2619
2914
        o.decode(b)
2620
2915
        self.assertEqual(o.code, 1)
2621
2916
        self.assertEqual(o.data, b'foobar')
 
2917
 
 
2918
 
 
2919
 
 
2920
class RaisedArgs(Exception):
 
2921
    """
 
2922
    An exception which can be raised by fakes to test that the fake is called
 
2923
    with expected arguments.
 
2924
    """
 
2925
    def __init__(self, args, kwargs):
 
2926
        """
 
2927
        Store the positional and keyword arguments as attributes.
 
2928
 
 
2929
        @param args: The positional args.
 
2930
        @param kwargs: The keyword args.
 
2931
        """
 
2932
        self.args = args
 
2933
        self.kwargs = kwargs
 
2934
 
 
2935
 
 
2936
 
 
2937
class MessageEmpty(object):
 
2938
    """
 
2939
    Generate byte string and constructor arguments for an empty
 
2940
    L{dns._EDNSMessage}.
 
2941
    """
 
2942
    @classmethod
 
2943
    def bytes(cls):
 
2944
        """
 
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
 
2947
        decoded.
 
2948
 
 
2949
        @return: The L{bytes} of a wire encoded message.
 
2950
        """
 
2951
        return (
 
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
 
2959
        )
 
2960
 
 
2961
 
 
2962
    @classmethod
 
2963
    def kwargs(cls):
 
2964
        """
 
2965
        Keyword constructor arguments which are expected to result in an
 
2966
        instance which returns C{bytes} when encoded.
 
2967
 
 
2968
        @return: A L{dict} of keyword arguments.
 
2969
        """
 
2970
        return dict(
 
2971
            id=256,
 
2972
            answer=True,
 
2973
            opCode=dns.OP_STATUS,
 
2974
            auth=True,
 
2975
            trunc=True,
 
2976
            recDes=True,
 
2977
            recAv=True,
 
2978
            rCode=15,
 
2979
            ednsVersion=None,
 
2980
        )
 
2981
 
 
2982
 
 
2983
 
 
2984
class MessageTruncated(object):
 
2985
    """
 
2986
    An empty response message whose TR bit is set to 1.
 
2987
    """
 
2988
    @classmethod
 
2989
    def bytes(cls):
 
2990
        """
 
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
 
2993
        decoded.
 
2994
 
 
2995
        @return: The L{bytes} of a wire encoded message.
 
2996
        """
 
2997
        return (
 
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
 
3005
        )
 
3006
 
 
3007
 
 
3008
    @classmethod
 
3009
    def kwargs(cls):
 
3010
        """
 
3011
        Keyword constructor arguments which are expected to result in an
 
3012
        instance which returns C{bytes} when encoded.
 
3013
 
 
3014
        @return: A L{dict} of keyword arguments.
 
3015
        """
 
3016
        return dict(
 
3017
            id=256,
 
3018
            answer=1,
 
3019
            opCode=0,
 
3020
            auth=0,
 
3021
            trunc=1,
 
3022
            recDes=0,
 
3023
            recAv=0,
 
3024
            rCode=0,
 
3025
            ednsVersion=None,)
 
3026
 
 
3027
 
 
3028
 
 
3029
class MessageNonAuthoritative(object):
 
3030
    """
 
3031
    A minimal non-authoritative message.
 
3032
    """
 
3033
    @classmethod
 
3034
    def bytes(cls):
 
3035
        """
 
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
 
3038
        decoded.
 
3039
 
 
3040
        @return: The L{bytes} of a wire encoded message.
 
3041
        """
 
3042
        return (
 
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
 
3050
            # Answer
 
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
 
3057
        )
 
3058
 
 
3059
 
 
3060
    @classmethod
 
3061
    def kwargs(cls):
 
3062
        """
 
3063
        Keyword constructor arguments which are expected to result in an
 
3064
        instance which returns C{bytes} when encoded.
 
3065
 
 
3066
        @return: A L{dict} of keyword arguments.
 
3067
        """
 
3068
        return dict(
 
3069
            id=256,
 
3070
            auth=0,
 
3071
            ednsVersion=None,
 
3072
            answers=[
 
3073
                dns.RRHeader(
 
3074
                    b'',
 
3075
                    payload=dns.Record_A('1.2.3.4', ttl=0),
 
3076
                    auth=False)])
 
3077
 
 
3078
 
 
3079
 
 
3080
class MessageAuthoritative(object):
 
3081
    """
 
3082
    A minimal authoritative message.
 
3083
    """
 
3084
    @classmethod
 
3085
    def bytes(cls):
 
3086
        """
 
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
 
3089
        decoded.
 
3090
 
 
3091
        @return: The L{bytes} of a wire encoded message.
 
3092
        """
 
3093
        return (
 
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
 
3101
            # Answer
 
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
 
3108
        )
 
3109
 
 
3110
 
 
3111
    @classmethod
 
3112
    def kwargs(cls):
 
3113
        """
 
3114
        Keyword constructor arguments which are expected to result in an
 
3115
        instance which returns C{bytes} when encoded.
 
3116
 
 
3117
        @return: A L{dict} of keyword arguments.
 
3118
        """
 
3119
        return dict(
 
3120
            id=256,
 
3121
            auth=1,
 
3122
            ednsVersion=None,
 
3123
            answers=[
 
3124
                dns.RRHeader(
 
3125
                    b'',
 
3126
                    payload=dns.Record_A('1.2.3.4', ttl=0),
 
3127
                    auth=True)])
 
3128
 
 
3129
 
 
3130
 
 
3131
class MessageComplete:
 
3132
    """
 
3133
    An example of a fully populated non-edns response message.
 
3134
 
 
3135
    Contains name compression, answers, authority, and additional records.
 
3136
    """
 
3137
    @classmethod
 
3138
    def bytes(cls):
 
3139
        """
 
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
 
3142
        decoded.
 
3143
 
 
3144
        @return: The L{bytes} of a wire encoded message.
 
3145
        """
 
3146
        return (
 
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
 
3154
 
 
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)
 
3159
 
 
3160
            # Answers
 
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
 
3173
 
 
3174
            # Authority
 
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)
 
3181
 
 
3182
            # Additional
 
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
 
3189
        )
 
3190
 
 
3191
 
 
3192
    @classmethod
 
3193
    def kwargs(cls):
 
3194
        """
 
3195
        Keyword constructor arguments which are expected to result in an
 
3196
        instance which returns C{bytes} when encoded.
 
3197
 
 
3198
        @return: A L{dict} of keyword arguments.
 
3199
        """
 
3200
        return dict(
 
3201
            id=256,
 
3202
            answer=1,
 
3203
            opCode=dns.OP_STATUS,
 
3204
            auth=1,
 
3205
            recDes=1,
 
3206
            recAv=1,
 
3207
            rCode=15,
 
3208
            ednsVersion=None,
 
3209
            queries=[dns.Query(b'example.com', dns.SOA)],
 
3210
            answers=[
 
3211
                dns.RRHeader(
 
3212
                    b'example.com',
 
3213
                    type=dns.SOA,
 
3214
                    ttl=0xffffffff,
 
3215
                    auth=True,
 
3216
                    payload=dns.Record_SOA(
 
3217
                        ttl=0xffffffff,
 
3218
                        mname=b'ns1.example.com',
 
3219
                        rname=b'hostmaster.example.com',
 
3220
                        serial=0xfffffffe,
 
3221
                        refresh=0x7ffffffd,
 
3222
                        retry=0x7ffffffc,
 
3223
                        expire=0x7ffffffb,
 
3224
                        minimum=0xfffffffa,
 
3225
                        ))],
 
3226
            authority=[
 
3227
                dns.RRHeader(
 
3228
                    b'example.com',
 
3229
                    type=dns.NS,
 
3230
                    ttl=0xffffffff,
 
3231
                    auth=True,
 
3232
                    payload=dns.Record_NS(
 
3233
                        'ns1.example.com', ttl=0xffffffff))],
 
3234
            additional=[
 
3235
                dns.RRHeader(
 
3236
                    b'ns1.example.com',
 
3237
                    type=dns.A,
 
3238
                    ttl=0xffffffff,
 
3239
                    auth=True,
 
3240
                    payload=dns.Record_A(
 
3241
                        '5.6.7.8', ttl=0xffffffff))])
 
3242
 
 
3243
 
 
3244
 
 
3245
class MessageEDNSQuery(object):
 
3246
    """
 
3247
    A minimal EDNS query message.
 
3248
    """
 
3249
    @classmethod
 
3250
    def bytes(cls):
 
3251
        """
 
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
 
3254
        decoded.
 
3255
 
 
3256
        @return: The L{bytes} of a wire encoded message.
 
3257
        """
 
3258
        return (
 
3259
            b'\x00\x00' # ID: 0
 
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
 
3266
 
 
3267
            # Queries
 
3268
            b'\x03www\x07example\x03com\x00' # QNAME
 
3269
            b'\x00\x01' # QTYPE (A)
 
3270
            b'\x00\x01' # QCLASS (IN)
 
3271
 
 
3272
            # Additional OPT record
 
3273
            b'\x00' # NAME (.)
 
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
 
3280
        )
 
3281
 
 
3282
 
 
3283
    @classmethod
 
3284
    def kwargs(cls):
 
3285
        """
 
3286
        Keyword constructor arguments which are expected to result in an
 
3287
        instance which returns C{bytes} when encoded.
 
3288
 
 
3289
        @return: A L{dict} of keyword arguments.
 
3290
        """
 
3291
        return dict(
 
3292
            id=0,
 
3293
            answer=0,
 
3294
            opCode=dns.OP_QUERY,
 
3295
            auth=0,
 
3296
            recDes=0,
 
3297
            recAv=0,
 
3298
            rCode=0,
 
3299
            ednsVersion=3,
 
3300
            dnssecOK=False,
 
3301
            queries=[dns.Query(b'www.example.com', dns.A)],
 
3302
            additional=[])
 
3303
 
 
3304
 
 
3305
 
 
3306
class MessageEDNSComplete(object):
 
3307
    """
 
3308
    An example of a fully populated edns response message.
 
3309
 
 
3310
    Contains name compression, answers, authority, and additional records.
 
3311
    """
 
3312
    @classmethod
 
3313
    def bytes(cls):
 
3314
        """
 
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
 
3317
        decoded.
 
3318
 
 
3319
        @return: The L{bytes} of a wire encoded message.
 
3320
        """
 
3321
        return (
 
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
 
3329
 
 
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)
 
3334
 
 
3335
            # Answers
 
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
 
3348
 
 
3349
            # Authority
 
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)
 
3356
 
 
3357
            # Additional
 
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
 
3364
 
 
3365
            # Additional OPT record
 
3366
            b'\x00' # NAME (.)
 
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
 
3373
        )
 
3374
 
 
3375
 
 
3376
    @classmethod
 
3377
    def kwargs(cls):
 
3378
        """
 
3379
        Keyword constructor arguments which are expected to result in an
 
3380
        instance which returns C{bytes} when encoded.
 
3381
 
 
3382
        @return: A L{dict} of keyword arguments.
 
3383
        """
 
3384
        return dict(
 
3385
            id=256,
 
3386
            answer=1,
 
3387
            opCode=dns.OP_STATUS,
 
3388
            auth=1,
 
3389
            trunc=0,
 
3390
            recDes=1,
 
3391
            recAv=1,
 
3392
            rCode=15,
 
3393
            ednsVersion=3,
 
3394
            dnssecOK=True,
 
3395
            authenticData=True,
 
3396
            checkingDisabled=True,
 
3397
            maxSize=1024,
 
3398
            queries=[dns.Query(b'example.com', dns.SOA)],
 
3399
            answers=[
 
3400
                dns.RRHeader(
 
3401
                    b'example.com',
 
3402
                    type=dns.SOA,
 
3403
                    ttl=0xffffffff,
 
3404
                    auth=True,
 
3405
                    payload=dns.Record_SOA(
 
3406
                        ttl=0xffffffff,
 
3407
                        mname=b'ns1.example.com',
 
3408
                        rname=b'hostmaster.example.com',
 
3409
                        serial=0xfffffffe,
 
3410
                        refresh=0x7ffffffd,
 
3411
                        retry=0x7ffffffc,
 
3412
                        expire=0x7ffffffb,
 
3413
                        minimum=0xfffffffa,
 
3414
                        ))],
 
3415
            authority=[
 
3416
                dns.RRHeader(
 
3417
                    b'example.com',
 
3418
                    type=dns.NS,
 
3419
                    ttl=0xffffffff,
 
3420
                    auth=True,
 
3421
                    payload=dns.Record_NS(
 
3422
                        'ns1.example.com', ttl=0xffffffff))],
 
3423
            additional=[
 
3424
                dns.RRHeader(
 
3425
                    b'ns1.example.com',
 
3426
                    type=dns.A,
 
3427
                    ttl=0xffffffff,
 
3428
                    auth=True,
 
3429
                    payload=dns.Record_A(
 
3430
                        '5.6.7.8', ttl=0xffffffff))])
 
3431
 
 
3432
 
 
3433
 
 
3434
class MessageEDNSExtendedRCODE(object):
 
3435
    """
 
3436
    An example of an EDNS message with an extended RCODE.
 
3437
    """
 
3438
    @classmethod
 
3439
    def bytes(cls):
 
3440
        """
 
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
 
3443
        decoded.
 
3444
 
 
3445
        @return: The L{bytes} of a wire encoded message.
 
3446
        """
 
3447
        return (
 
3448
            b'\x00\x00'
 
3449
            b'\x00'
 
3450
            b'\x0c' # RA: 0, Z, RCODE: 12
 
3451
            b'\x00\x00'
 
3452
            b'\x00\x00'
 
3453
            b'\x00\x00'
 
3454
            b'\x00\x01' # 1 additionals
 
3455
 
 
3456
            # Additional OPT record
 
3457
            b'\x00'
 
3458
            b'\x00\x29'
 
3459
            b'\x10\x00'
 
3460
            b'\xab' # Extended RCODE: 171
 
3461
            b'\x00'
 
3462
            b'\x00\x00'
 
3463
            b'\x00\x00'
 
3464
        )
 
3465
 
 
3466
 
 
3467
    @classmethod
 
3468
    def kwargs(cls):
 
3469
        """
 
3470
        Keyword constructor arguments which are expected to result in an
 
3471
        instance which returns C{bytes} when encoded.
 
3472
 
 
3473
        @return: A L{dict} of keyword arguments.
 
3474
        """
 
3475
        return dict(
 
3476
            id=0,
 
3477
            answer=False,
 
3478
            opCode=dns.OP_QUERY,
 
3479
            auth=False,
 
3480
            trunc=False,
 
3481
            recDes=False,
 
3482
            recAv=False,
 
3483
            rCode=0xabc, # Combined OPT extended RCODE + Message RCODE
 
3484
            ednsVersion=0,
 
3485
            dnssecOK=False,
 
3486
            maxSize=4096,
 
3487
            queries=[],
 
3488
            answers=[],
 
3489
            authority=[],
 
3490
            additional=[],
 
3491
        )
 
3492
 
 
3493
 
 
3494
 
 
3495
class MessageComparable(FancyEqMixin, FancyStrMixin, object):
 
3496
    """
 
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.
 
3499
    """
 
3500
    showAttributes = compareAttributes = (
 
3501
        'id', 'answer', 'opCode', 'auth', 'trunc',
 
3502
        'recDes', 'recAv', 'rCode',
 
3503
        'queries', 'answers', 'authority', 'additional')
 
3504
 
 
3505
    def __init__(self, original):
 
3506
        self.original = original
 
3507
 
 
3508
 
 
3509
    def __getattr__(self, key):
 
3510
        return getattr(self.original, key)
 
3511
 
 
3512
 
 
3513
 
 
3514
def verifyConstructorArgument(testCase, cls, argName, defaultVal, altVal,
 
3515
                              attrName=None):
 
3516
    """
 
3517
    Verify that an attribute has the expected default value and that a
 
3518
    corresponding argument passed to a constructor is assigned to that
 
3519
    attribute.
 
3520
 
 
3521
    @param testCase: The L{TestCase} whose assert methods will be
 
3522
        called.
 
3523
    @type testCase: L{unittest.TestCase}
 
3524
 
 
3525
    @param cls: The constructor under test.
 
3526
    @type cls: L{type}
 
3527
 
 
3528
    @param argName: The name of the constructor argument under test.
 
3529
    @type argName: L{str}
 
3530
 
 
3531
    @param defaultVal: The expected default value of C{attrName} /
 
3532
        C{argName}
 
3533
    @type defaultVal: L{object}
 
3534
 
 
3535
    @param altVal: A value which is different from the default. Used to
 
3536
        test that supplied constructor arguments are actually assigned to the
 
3537
        correct attribute.
 
3538
    @type altVal: L{object}
 
3539
 
 
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}
 
3543
    """
 
3544
    if attrName is None:
 
3545
        attrName = argName
 
3546
 
 
3547
    actual = {}
 
3548
    expected = {'defaultVal': defaultVal, 'altVal': altVal}
 
3549
 
 
3550
    o = cls()
 
3551
    actual['defaultVal'] = getattr(o, attrName)
 
3552
 
 
3553
    o = cls(**{argName: altVal})
 
3554
    actual['altVal'] = getattr(o, attrName)
 
3555
 
 
3556
    testCase.assertEqual(expected, actual)
 
3557
 
 
3558
 
 
3559
 
 
3560
class ConstructorTestsMixin(object):
 
3561
    """
 
3562
    Helper methods for verifying default attribute values and corresponding
 
3563
    constructor arguments.
 
3564
    """
 
3565
    def _verifyConstructorArgument(self, argName, defaultVal, altVal):
 
3566
        """
 
3567
        Wrap L{verifyConstructorArgument} to provide simpler interface for
 
3568
        testing Message and _EDNSMessage constructor arguments.
 
3569
 
 
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.
 
3574
        """
 
3575
        verifyConstructorArgument(testCase=self, cls=self.messageFactory,
 
3576
                                  argName=argName, defaultVal=defaultVal,
 
3577
                                  altVal=altVal)
 
3578
 
 
3579
 
 
3580
    def _verifyConstructorFlag(self, argName, defaultVal):
 
3581
        """
 
3582
        Wrap L{verifyConstructorArgument} to provide simpler interface for
 
3583
        testing  _EDNSMessage constructor flags.
 
3584
 
 
3585
        @param argName: The name of the constructor flag argument
 
3586
        @param defaultVal: The expected default value of the flag
 
3587
        """
 
3588
        assert defaultVal in (True, False)
 
3589
        verifyConstructorArgument(testCase=self, cls=self.messageFactory,
 
3590
                                  argName=argName, defaultVal=defaultVal,
 
3591
                                  altVal=not defaultVal,)
 
3592
 
 
3593
 
 
3594
 
 
3595
class CommonConstructorTestsMixin(object):
 
3596
    """
 
3597
    Tests for constructor arguments and their associated attributes that are
 
3598
    common to both L{twisted.names.dns._EDNSMessage} and L{dns.Message}.
 
3599
 
 
3600
    TestCase classes that use this mixin must provide a C{messageFactory} method
 
3601
    which accepts any argment supported by L{dns.Message.__init__}.
 
3602
 
 
3603
    TestCases must also mixin ConstructorTestsMixin which provides some custom
 
3604
    assertions for testing constructor arguments.
 
3605
    """
 
3606
    def test_id(self):
 
3607
        """
 
3608
        L{dns._EDNSMessage.id} defaults to C{0} and can be overridden in
 
3609
        the constructor.
 
3610
        """
 
3611
        self._verifyConstructorArgument('id', defaultVal=0, altVal=1)
 
3612
 
 
3613
 
 
3614
    def test_answer(self):
 
3615
        """
 
3616
        L{dns._EDNSMessage.answer} defaults to C{False} and can be overridden in
 
3617
        the constructor.
 
3618
        """
 
3619
        self._verifyConstructorFlag('answer', defaultVal=False)
 
3620
 
 
3621
 
 
3622
    def test_opCode(self):
 
3623
        """
 
3624
        L{dns._EDNSMessage.opCode} defaults to L{dns.OP_QUERY} and can be
 
3625
        overridden in the constructor.
 
3626
        """
 
3627
        self._verifyConstructorArgument(
 
3628
            'opCode', defaultVal=dns.OP_QUERY, altVal=dns.OP_STATUS)
 
3629
 
 
3630
 
 
3631
    def test_auth(self):
 
3632
        """
 
3633
        L{dns._EDNSMessage.auth} defaults to C{False} and can be overridden in
 
3634
        the constructor.
 
3635
        """
 
3636
        self._verifyConstructorFlag('auth', defaultVal=False)
 
3637
 
 
3638
 
 
3639
    def test_trunc(self):
 
3640
        """
 
3641
        L{dns._EDNSMessage.trunc} defaults to C{False} and can be overridden in
 
3642
        the constructor.
 
3643
        """
 
3644
        self._verifyConstructorFlag('trunc', defaultVal=False)
 
3645
 
 
3646
 
 
3647
    def test_recDes(self):
 
3648
        """
 
3649
        L{dns._EDNSMessage.recDes} defaults to C{False} and can be overridden in
 
3650
        the constructor.
 
3651
        """
 
3652
        self._verifyConstructorFlag('recDes', defaultVal=False)
 
3653
 
 
3654
 
 
3655
    def test_recAv(self):
 
3656
        """
 
3657
        L{dns._EDNSMessage.recAv} defaults to C{False} and can be overridden in
 
3658
        the constructor.
 
3659
        """
 
3660
        self._verifyConstructorFlag('recAv', defaultVal=False)
 
3661
 
 
3662
 
 
3663
    def test_rCode(self):
 
3664
        """
 
3665
        L{dns._EDNSMessage.rCode} defaults to C{0} and can be overridden in the
 
3666
        constructor.
 
3667
        """
 
3668
        self._verifyConstructorArgument('rCode', defaultVal=0, altVal=123)
 
3669
 
 
3670
 
 
3671
    def test_maxSize(self):
 
3672
        """
 
3673
        L{dns._EDNSMessage.maxSize} defaults to C{512} and can be overridden in
 
3674
        the constructor.
 
3675
        """
 
3676
        self._verifyConstructorArgument('maxSize', defaultVal=512, altVal=1024)
 
3677
 
 
3678
 
 
3679
    def test_queries(self):
 
3680
        """
 
3681
        L{dns._EDNSMessage.queries} defaults to C{[]}.
 
3682
        """
 
3683
        self.assertEqual(self.messageFactory().queries, [])
 
3684
 
 
3685
 
 
3686
    def test_answers(self):
 
3687
        """
 
3688
        L{dns._EDNSMessage.answers} defaults to C{[]}.
 
3689
        """
 
3690
        self.assertEqual(self.messageFactory().answers, [])
 
3691
 
 
3692
 
 
3693
    def test_authority(self):
 
3694
        """
 
3695
        L{dns._EDNSMessage.authority} defaults to C{[]}.
 
3696
        """
 
3697
        self.assertEqual(self.messageFactory().authority, [])
 
3698
 
 
3699
 
 
3700
    def test_additional(self):
 
3701
        """
 
3702
        L{dns._EDNSMessage.additional} defaults to C{[]}.
 
3703
        """
 
3704
        self.assertEqual(self.messageFactory().additional, [])
 
3705
 
 
3706
 
 
3707
 
 
3708
class EDNSMessageConstructorTests(ConstructorTestsMixin,
 
3709
                                  CommonConstructorTestsMixin,
 
3710
                                  unittest.SynchronousTestCase):
 
3711
    """
 
3712
    Tests for L{twisted.names.dns._EDNSMessage} constructor arguments that are
 
3713
    shared with L{dns.Message}.
 
3714
    """
 
3715
    messageFactory = dns._EDNSMessage
 
3716
 
 
3717
 
 
3718
 
 
3719
class MessageConstructorTests(ConstructorTestsMixin,
 
3720
                               CommonConstructorTestsMixin,
 
3721
                               unittest.SynchronousTestCase):
 
3722
    """
 
3723
    Tests for L{twisted.names.dns.Message} constructor arguments that are shared
 
3724
    with L{dns._EDNSMessage}.
 
3725
    """
 
3726
    messageFactory = dns.Message
 
3727
 
 
3728
 
 
3729
 
 
3730
class EDNSMessageSpecificsTestCase(ConstructorTestsMixin,
 
3731
                                   unittest.SynchronousTestCase):
 
3732
    """
 
3733
    Tests for L{dns._EDNSMessage}.
 
3734
 
 
3735
    These tests are for L{dns._EDNSMessage} APIs which are not shared with
 
3736
    L{dns.Message}.
 
3737
    """
 
3738
    messageFactory = dns._EDNSMessage
 
3739
 
 
3740
    def test_ednsVersion(self):
 
3741
        """
 
3742
        L{dns._EDNSMessage.ednsVersion} defaults to C{0} and can be overridden
 
3743
        in the constructor.
 
3744
        """
 
3745
        self._verifyConstructorArgument(
 
3746
            'ednsVersion', defaultVal=0, altVal=None)
 
3747
 
 
3748
 
 
3749
    def test_dnssecOK(self):
 
3750
        """
 
3751
        L{dns._EDNSMessage.dnssecOK} defaults to C{False} and can be overridden
 
3752
        in the constructor.
 
3753
        """
 
3754
        self._verifyConstructorFlag('dnssecOK', defaultVal=False)
 
3755
 
 
3756
 
 
3757
    def test_authenticData(self):
 
3758
        """
 
3759
        L{dns._EDNSMessage.authenticData} defaults to C{False} and can be
 
3760
        overridden in the constructor.
 
3761
        """
 
3762
        self._verifyConstructorFlag('authenticData', defaultVal=False)
 
3763
 
 
3764
 
 
3765
    def test_checkingDisabled(self):
 
3766
        """
 
3767
        L{dns._EDNSMessage.checkingDisabled} defaults to C{False} and can be
 
3768
        overridden in the constructor.
 
3769
        """
 
3770
        self._verifyConstructorFlag('checkingDisabled', defaultVal=False)
 
3771
 
 
3772
 
 
3773
    def test_queriesOverride(self):
 
3774
        """
 
3775
        L{dns._EDNSMessage.queries} can be overridden in the constructor.
 
3776
        """
 
3777
        msg = self.messageFactory(queries=[dns.Query(b'example.com')])
 
3778
 
 
3779
        self.assertEqual(
 
3780
            msg.queries,
 
3781
            [dns.Query(b'example.com')])
 
3782
 
 
3783
 
 
3784
    def test_answersOverride(self):
 
3785
        """
 
3786
        L{dns._EDNSMessage.answers} can be overridden in the constructor.
 
3787
        """
 
3788
        msg = self.messageFactory(
 
3789
            answers=[
 
3790
                dns.RRHeader(
 
3791
                    b'example.com',
 
3792
                    payload=dns.Record_A('1.2.3.4'))])
 
3793
 
 
3794
        self.assertEqual(
 
3795
            msg.answers,
 
3796
            [dns.RRHeader(b'example.com', payload=dns.Record_A('1.2.3.4'))])
 
3797
 
 
3798
 
 
3799
    def test_authorityOverride(self):
 
3800
        """
 
3801
        L{dns._EDNSMessage.authority} can be overridden in the constructor.
 
3802
        """
 
3803
        msg = self.messageFactory(
 
3804
            authority=[
 
3805
                dns.RRHeader(
 
3806
                    b'example.com',
 
3807
                    type=dns.SOA,
 
3808
                    payload=dns.Record_SOA())])
 
3809
 
 
3810
        self.assertEqual(
 
3811
            msg.authority,
 
3812
            [dns.RRHeader(b'example.com', type=dns.SOA,
 
3813
                          payload=dns.Record_SOA())])
 
3814
 
 
3815
 
 
3816
    def test_additionalOverride(self):
 
3817
        """
 
3818
        L{dns._EDNSMessage.authority} can be overridden in the constructor.
 
3819
        """
 
3820
        msg = self.messageFactory(
 
3821
            additional=[
 
3822
                dns.RRHeader(
 
3823
                    b'example.com',
 
3824
                    payload=dns.Record_A('1.2.3.4'))])
 
3825
 
 
3826
        self.assertEqual(
 
3827
            msg.additional,
 
3828
            [dns.RRHeader(b'example.com', payload=dns.Record_A('1.2.3.4'))])
 
3829
 
 
3830
 
 
3831
    def test_reprDefaults(self):
 
3832
        """
 
3833
        L{dns._EDNSMessage.__repr__} omits field values and sections which are
 
3834
        identical to their defaults. The id field value is always shown.
 
3835
        """
 
3836
        self.assertEqual(
 
3837
            '<_EDNSMessage id=0>',
 
3838
            repr(self.messageFactory())
 
3839
        )
 
3840
 
 
3841
 
 
3842
    def test_reprFlagsIfSet(self):
 
3843
        """
 
3844
        L{dns._EDNSMessage.__repr__} displays flags if they are L{True}.
 
3845
        """
 
3846
        m = self.messageFactory(answer=True, auth=True, trunc=True, recDes=True,
 
3847
                                recAv=True, authenticData=True,
 
3848
                                checkingDisabled=True, dnssecOK=True)
 
3849
        self.assertEqual(
 
3850
            '<_EDNSMessage '
 
3851
            'id=0 '
 
3852
            'flags=answer,auth,trunc,recDes,recAv,authenticData,'
 
3853
            'checkingDisabled,dnssecOK'
 
3854
            '>',
 
3855
            repr(m),
 
3856
        )
 
3857
 
 
3858
 
 
3859
    def test_reprNonDefautFields(self):
 
3860
        """
 
3861
        L{dns._EDNSMessage.__repr__} displays field values if they differ from
 
3862
        their defaults.
 
3863
        """
 
3864
        m = self.messageFactory(id=10, opCode=20, rCode=30, maxSize=40,
 
3865
                                ednsVersion=50)
 
3866
        self.assertEqual(
 
3867
            '<_EDNSMessage '
 
3868
            'id=10 '
 
3869
            'opCode=20 '
 
3870
            'rCode=30 '
 
3871
            'maxSize=40 '
 
3872
            'ednsVersion=50'
 
3873
            '>',
 
3874
            repr(m),
 
3875
        )
 
3876
 
 
3877
 
 
3878
    def test_reprNonDefaultSections(self):
 
3879
        """
 
3880
        L{dns.Message.__repr__} displays sections which differ from their
 
3881
        defaults.
 
3882
        """
 
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]
 
3888
        self.assertEqual(
 
3889
            '<_EDNSMessage '
 
3890
            'id=0 '
 
3891
            'queries=[1, 2, 3] '
 
3892
            'answers=[4, 5, 6] '
 
3893
            'authority=[7, 8, 9] '
 
3894
            'additional=[10, 11, 12]'
 
3895
            '>',
 
3896
            repr(m),
 
3897
        )
 
3898
 
 
3899
 
 
3900
    def test_fromStrCallsMessageFactory(self):
 
3901
        """
 
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
 
3904
        supplied bytes.
 
3905
        """
 
3906
        class FakeMessageFactory(object):
 
3907
            """
 
3908
            Fake message factory.
 
3909
            """
 
3910
            def fromStr(self, *args, **kwargs):
 
3911
                """
 
3912
                Fake fromStr method which raises the arguments it was passed.
 
3913
 
 
3914
                @param args: positional arguments
 
3915
                @param kwargs: keyword arguments
 
3916
                """
 
3917
                raise RaisedArgs(args, kwargs)
 
3918
 
 
3919
        m = dns._EDNSMessage()
 
3920
        m._messageFactory = FakeMessageFactory
 
3921
        dummyBytes = object()
 
3922
        e = self.assertRaises(RaisedArgs, m.fromStr, dummyBytes)
 
3923
        self.assertEqual(
 
3924
            ((dummyBytes,), {}),
 
3925
            (e.args, e.kwargs)
 
3926
        )
 
3927
 
 
3928
 
 
3929
    def test_fromStrCallsFromMessage(self):
 
3930
        """
 
3931
        L{dns._EDNSMessage.fromString} calls L{dns._EDNSMessage._fromMessage}
 
3932
        with a L{dns.Message} instance
 
3933
        """
 
3934
        m = dns._EDNSMessage()
 
3935
        class FakeMessageFactory():
 
3936
            """
 
3937
            Fake message factory.
 
3938
            """
 
3939
            def fromStr(self, bytes):
 
3940
                """
 
3941
                A noop fake version of fromStr
 
3942
 
 
3943
                @param bytes: the bytes to be decoded
 
3944
                """
 
3945
 
 
3946
        fakeMessage = FakeMessageFactory()
 
3947
        m._messageFactory = lambda: fakeMessage
 
3948
 
 
3949
        def fakeFromMessage(*args, **kwargs):
 
3950
            raise RaisedArgs(args, kwargs)
 
3951
        m._fromMessage = fakeFromMessage
 
3952
        e = self.assertRaises(RaisedArgs, m.fromStr, b'')
 
3953
        self.assertEqual(
 
3954
            ((fakeMessage,), {}),
 
3955
            (e.args, e.kwargs)
 
3956
        )
 
3957
 
 
3958
 
 
3959
    def test_toStrCallsToMessage(self):
 
3960
        """
 
3961
        L{dns._EDNSMessage.toStr} calls L{dns._EDNSMessage._toMessage}
 
3962
        """
 
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)
 
3968
        self.assertEqual(
 
3969
            ((), {}),
 
3970
            (e.args, e.kwargs)
 
3971
        )
 
3972
 
 
3973
 
 
3974
    def test_toStrCallsToMessageToStr(self):
 
3975
        """
 
3976
        L{dns._EDNSMessage.toStr} calls C{toStr} on the message returned by
 
3977
        L{dns._EDNSMessage._toMessage}.
 
3978
        """
 
3979
        m = dns._EDNSMessage()
 
3980
        dummyBytes = object()
 
3981
        class FakeMessage(object):
 
3982
            """
 
3983
            Fake Message
 
3984
            """
 
3985
            def toStr(self):
 
3986
                """
 
3987
                Fake toStr which returns dummyBytes.
 
3988
 
 
3989
                @return: dummyBytes
 
3990
                """
 
3991
                return dummyBytes
 
3992
 
 
3993
        def fakeToMessage(*args, **kwargs):
 
3994
            return FakeMessage()
 
3995
        m._toMessage = fakeToMessage
 
3996
 
 
3997
        self.assertEqual(
 
3998
            dummyBytes,
 
3999
            m.toStr()
 
4000
        )
 
4001
 
 
4002
 
 
4003
 
 
4004
class EDNSMessageEqualityTests(ComparisonTestsMixin, unittest.SynchronousTestCase):
 
4005
    """
 
4006
    Tests for equality between L(dns._EDNSMessage} instances.
 
4007
 
 
4008
    These tests will not work with L{dns.Message} because it does not use
 
4009
    L{twisted.python.util.FancyEqMixin}.
 
4010
    """
 
4011
 
 
4012
    messageFactory = dns._EDNSMessage
 
4013
 
 
4014
    def test_id(self):
 
4015
        """
 
4016
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4017
        id.
 
4018
        """
 
4019
        self.assertNormalEqualityImplementation(
 
4020
            self.messageFactory(id=1),
 
4021
            self.messageFactory(id=1),
 
4022
            self.messageFactory(id=2),
 
4023
            )
 
4024
 
 
4025
 
 
4026
    def test_answer(self):
 
4027
        """
 
4028
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4029
        answer flag.
 
4030
        """
 
4031
        self.assertNormalEqualityImplementation(
 
4032
            self.messageFactory(answer=True),
 
4033
            self.messageFactory(answer=True),
 
4034
            self.messageFactory(answer=False),
 
4035
            )
 
4036
 
 
4037
 
 
4038
    def test_opCode(self):
 
4039
        """
 
4040
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4041
        opCode.
 
4042
        """
 
4043
        self.assertNormalEqualityImplementation(
 
4044
            self.messageFactory(opCode=dns.OP_STATUS),
 
4045
            self.messageFactory(opCode=dns.OP_STATUS),
 
4046
            self.messageFactory(opCode=dns.OP_INVERSE),
 
4047
            )
 
4048
 
 
4049
 
 
4050
    def test_auth(self):
 
4051
        """
 
4052
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4053
        auth flag.
 
4054
        """
 
4055
        self.assertNormalEqualityImplementation(
 
4056
            self.messageFactory(auth=True),
 
4057
            self.messageFactory(auth=True),
 
4058
            self.messageFactory(auth=False),
 
4059
            )
 
4060
 
 
4061
 
 
4062
    def test_trunc(self):
 
4063
        """
 
4064
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4065
        trunc flag.
 
4066
        """
 
4067
        self.assertNormalEqualityImplementation(
 
4068
            self.messageFactory(trunc=True),
 
4069
            self.messageFactory(trunc=True),
 
4070
            self.messageFactory(trunc=False),
 
4071
            )
 
4072
 
 
4073
 
 
4074
    def test_recDes(self):
 
4075
        """
 
4076
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4077
        recDes flag.
 
4078
        """
 
4079
        self.assertNormalEqualityImplementation(
 
4080
            self.messageFactory(recDes=True),
 
4081
            self.messageFactory(recDes=True),
 
4082
            self.messageFactory(recDes=False),
 
4083
            )
 
4084
 
 
4085
 
 
4086
    def test_recAv(self):
 
4087
        """
 
4088
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4089
        recAv flag.
 
4090
        """
 
4091
        self.assertNormalEqualityImplementation(
 
4092
            self.messageFactory(recAv=True),
 
4093
            self.messageFactory(recAv=True),
 
4094
            self.messageFactory(recAv=False),
 
4095
            )
 
4096
 
 
4097
 
 
4098
    def test_rCode(self):
 
4099
        """
 
4100
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4101
        rCode.
 
4102
        """
 
4103
        self.assertNormalEqualityImplementation(
 
4104
            self.messageFactory(rCode=16),
 
4105
            self.messageFactory(rCode=16),
 
4106
            self.messageFactory(rCode=15),
 
4107
            )
 
4108
 
 
4109
 
 
4110
    def test_ednsVersion(self):
 
4111
        """
 
4112
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4113
        ednsVersion.
 
4114
        """
 
4115
        self.assertNormalEqualityImplementation(
 
4116
            self.messageFactory(ednsVersion=1),
 
4117
            self.messageFactory(ednsVersion=1),
 
4118
            self.messageFactory(ednsVersion=None),
 
4119
            )
 
4120
 
 
4121
 
 
4122
    def test_dnssecOK(self):
 
4123
        """
 
4124
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4125
        dnssecOK.
 
4126
        """
 
4127
        self.assertNormalEqualityImplementation(
 
4128
            self.messageFactory(dnssecOK=True),
 
4129
            self.messageFactory(dnssecOK=True),
 
4130
            self.messageFactory(dnssecOK=False),
 
4131
            )
 
4132
 
 
4133
 
 
4134
    def test_authenticData(self):
 
4135
        """
 
4136
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4137
        authenticData flags.
 
4138
        """
 
4139
        self.assertNormalEqualityImplementation(
 
4140
            self.messageFactory(authenticData=True),
 
4141
            self.messageFactory(authenticData=True),
 
4142
            self.messageFactory(authenticData=False),
 
4143
            )
 
4144
 
 
4145
 
 
4146
    def test_checkingDisabled(self):
 
4147
        """
 
4148
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4149
        checkingDisabled flags.
 
4150
        """
 
4151
        self.assertNormalEqualityImplementation(
 
4152
            self.messageFactory(checkingDisabled=True),
 
4153
            self.messageFactory(checkingDisabled=True),
 
4154
            self.messageFactory(checkingDisabled=False),
 
4155
            )
 
4156
 
 
4157
 
 
4158
    def test_maxSize(self):
 
4159
        """
 
4160
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4161
        maxSize.
 
4162
        """
 
4163
        self.assertNormalEqualityImplementation(
 
4164
            self.messageFactory(maxSize=2048),
 
4165
            self.messageFactory(maxSize=2048),
 
4166
            self.messageFactory(maxSize=1024),
 
4167
            )
 
4168
 
 
4169
 
 
4170
    def test_queries(self):
 
4171
        """
 
4172
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4173
        queries.
 
4174
        """
 
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')]),
 
4179
            )
 
4180
 
 
4181
 
 
4182
    def test_answers(self):
 
4183
        """
 
4184
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4185
        answers.
 
4186
        """
 
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'))]),
 
4194
            )
 
4195
 
 
4196
 
 
4197
    def test_authority(self):
 
4198
        """
 
4199
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4200
        authority records.
 
4201
        """
 
4202
        self.assertNormalEqualityImplementation(
 
4203
            self.messageFactory(authority=[dns.RRHeader(
 
4204
                        b'example.com',
 
4205
                        type=dns.SOA, payload=dns.Record_SOA())]),
 
4206
            self.messageFactory(authority=[dns.RRHeader(
 
4207
                        b'example.com',
 
4208
                        type=dns.SOA, payload=dns.Record_SOA())]),
 
4209
            self.messageFactory(authority=[dns.RRHeader(
 
4210
                        b'example.org',
 
4211
                        type=dns.SOA, payload=dns.Record_SOA())]),
 
4212
            )
 
4213
 
 
4214
 
 
4215
    def test_additional(self):
 
4216
        """
 
4217
        Two L{dns._EDNSMessage} instances compare equal if they have the same
 
4218
        additional records.
 
4219
        """
 
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'))]),
 
4227
            )
 
4228
 
 
4229
 
 
4230
 
 
4231
class StandardEncodingTestsMixin(object):
 
4232
    """
 
4233
    Tests for the encoding and decoding of various standard (not EDNS) messages.
 
4234
 
 
4235
    These tests should work with both L{dns._EDNSMessage} and L{dns.Message}.
 
4236
 
 
4237
    TestCase classes that use this mixin must provide a C{messageFactory} method
 
4238
    which accepts any argment supported by L{dns._EDNSMessage.__init__}.
 
4239
 
 
4240
    EDNS specific arguments may be discarded if not supported by the message
 
4241
    class under construction.
 
4242
    """
 
4243
    def test_emptyMessageEncode(self):
 
4244
        """
 
4245
        An empty message can be encoded.
 
4246
        """
 
4247
        self.assertEqual(
 
4248
            self.messageFactory(**MessageEmpty.kwargs()).toStr(),
 
4249
            MessageEmpty.bytes())
 
4250
 
 
4251
 
 
4252
    def test_emptyMessageDecode(self):
 
4253
        """
 
4254
        An empty message byte sequence can be decoded.
 
4255
        """
 
4256
        m = self.messageFactory()
 
4257
        m.fromStr(MessageEmpty.bytes())
 
4258
 
 
4259
        self.assertEqual(m, self.messageFactory(**MessageEmpty.kwargs()))
 
4260
 
 
4261
 
 
4262
    def test_completeQueryEncode(self):
 
4263
        """
 
4264
        A fully populated query message can be encoded.
 
4265
        """
 
4266
        self.assertEqual(
 
4267
            self.messageFactory(**MessageComplete.kwargs()).toStr(),
 
4268
            MessageComplete.bytes())
 
4269
 
 
4270
 
 
4271
    def test_completeQueryDecode(self):
 
4272
        """
 
4273
        A fully populated message byte string can be decoded.
 
4274
        """
 
4275
        m = self.messageFactory()
 
4276
        m.fromStr(MessageComplete.bytes()),
 
4277
 
 
4278
        self.assertEqual(m, self.messageFactory(**MessageComplete.kwargs()))
 
4279
 
 
4280
 
 
4281
    def test_NULL(self):
 
4282
        """
 
4283
        A I{NULL} record with an arbitrary payload can be encoded and decoded as
 
4284
        part of a message.
 
4285
        """
 
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)
 
4291
        s = msg1.toStr()
 
4292
 
 
4293
        msg2 = self.messageFactory()
 
4294
        msg2.fromStr(s)
 
4295
 
 
4296
        self.assertIsInstance(msg2.answers[0].payload, dns.Record_NULL)
 
4297
        self.assertEqual(msg2.answers[0].payload.payload, bytes)
 
4298
 
 
4299
 
 
4300
    def test_nonAuthoritativeMessageEncode(self):
 
4301
        """
 
4302
        If the message C{authoritative} attribute is set to 0, the encoded bytes
 
4303
        will have AA bit 0.
 
4304
        """
 
4305
        self.assertEqual(
 
4306
            self.messageFactory(**MessageNonAuthoritative.kwargs()).toStr(),
 
4307
            MessageNonAuthoritative.bytes())
 
4308
 
 
4309
 
 
4310
    def test_nonAuthoritativeMessageDecode(self):
 
4311
        """
 
4312
        The L{dns.RRHeader} instances created by a message from a
 
4313
        non-authoritative message byte string are marked as not authoritative.
 
4314
        """
 
4315
        m = self.messageFactory()
 
4316
        m.fromStr(MessageNonAuthoritative.bytes())
 
4317
 
 
4318
        self.assertEqual(
 
4319
            m, self.messageFactory(**MessageNonAuthoritative.kwargs()))
 
4320
 
 
4321
 
 
4322
    def test_authoritativeMessageEncode(self):
 
4323
        """
 
4324
        If the message C{authoritative} attribute is set to 1, the encoded bytes
 
4325
        will have AA bit 1.
 
4326
        """
 
4327
        self.assertEqual(
 
4328
            self.messageFactory(**MessageAuthoritative.kwargs()).toStr(),
 
4329
            MessageAuthoritative.bytes())
 
4330
 
 
4331
 
 
4332
    def test_authoritativeMessageDecode(self):
 
4333
        """
 
4334
        The message and its L{dns.RRHeader} instances created by C{decode} from
 
4335
        an authoritative message byte string, are marked as authoritative.
 
4336
        """
 
4337
        m = self.messageFactory()
 
4338
        m.fromStr(MessageAuthoritative.bytes())
 
4339
 
 
4340
        self.assertEqual(
 
4341
            m, self.messageFactory(**MessageAuthoritative.kwargs()))
 
4342
 
 
4343
 
 
4344
    def test_truncatedMessageEncode(self):
 
4345
        """
 
4346
        If the message C{trunc} attribute is set to 1 the encoded bytes will
 
4347
        have TR bit 1.
 
4348
        """
 
4349
        self.assertEqual(
 
4350
            self.messageFactory(**MessageTruncated.kwargs()).toStr(),
 
4351
            MessageTruncated.bytes())
 
4352
 
 
4353
 
 
4354
    def test_truncatedMessageDecode(self):
 
4355
        """
 
4356
        The message instance created by decoding a truncated message is marked
 
4357
        as truncated.
 
4358
        """
 
4359
        m = self.messageFactory()
 
4360
        m.fromStr(MessageTruncated.bytes())
 
4361
 
 
4362
        self.assertEqual(m, self.messageFactory(**MessageTruncated.kwargs()))
 
4363
 
 
4364
 
 
4365
 
 
4366
class EDNSMessageStandardEncodingTests(StandardEncodingTestsMixin,
 
4367
                                       unittest.SynchronousTestCase):
 
4368
    """
 
4369
    Tests for the encoding and decoding of various standard (non-EDNS) messages
 
4370
    by L{dns._EDNSMessage}.
 
4371
    """
 
4372
    messageFactory = dns._EDNSMessage
 
4373
 
 
4374
 
 
4375
 
 
4376
class MessageStandardEncodingTests(StandardEncodingTestsMixin,
 
4377
                                   unittest.SynchronousTestCase):
 
4378
    """
 
4379
    Tests for the encoding and decoding of various standard (non-EDNS) messages
 
4380
    by L{dns.Message}.
 
4381
    """
 
4382
    @staticmethod
 
4383
    def messageFactory(**kwargs):
 
4384
        """
 
4385
        This function adapts constructor arguments expected by
 
4386
        _EDNSMessage.__init__ to arguments suitable for use with the
 
4387
        Message.__init__.
 
4388
 
 
4389
        Also handles the fact that unlike L{dns._EDNSMessage},
 
4390
        L{dns.Message.__init__} does not accept queries, answers etc as
 
4391
        arguments.
 
4392
 
 
4393
        Also removes any L{dns._EDNSMessage} specific arguments.
 
4394
 
 
4395
        @param args: The positional arguments which will be passed to
 
4396
            L{dns.Message.__init__}.
 
4397
 
 
4398
        @param kwargs: The keyword arguments which will be stripped of EDNS
 
4399
            specific arguments before being passed to L{dns.Message.__init__}.
 
4400
 
 
4401
        @return: An L{dns.Message} instance.
 
4402
        """
 
4403
        queries = kwargs.pop('queries', [])
 
4404
        answers = kwargs.pop('answers', [])
 
4405
        authority = kwargs.pop('authority', [])
 
4406
        additional = kwargs.pop('additional', [])
 
4407
 
 
4408
        kwargs.pop('ednsVersion', None)
 
4409
 
 
4410
        m = dns.Message(**kwargs)
 
4411
        m.queries = queries
 
4412
        m.answers = answers
 
4413
        m.authority = authority
 
4414
        m.additional = additional
 
4415
        return MessageComparable(m)
 
4416
 
 
4417
 
 
4418
 
 
4419
class EDNSMessageEDNSEncodingTests(unittest.SynchronousTestCase):
 
4420
    """
 
4421
    Tests for the encoding and decoding of various EDNS messages.
 
4422
 
 
4423
    These test will not work with L{dns.Message}.
 
4424
    """
 
4425
    messageFactory = dns._EDNSMessage
 
4426
 
 
4427
    def test_ednsMessageDecodeStripsOptRecords(self):
 
4428
        """
 
4429
        The L(_EDNSMessage} instance created by L{dns._EDNSMessage.decode} from
 
4430
        an EDNS query never includes OPT records in the additional section.
 
4431
        """
 
4432
        m = self.messageFactory()
 
4433
        m.fromStr(MessageEDNSQuery.bytes())
 
4434
 
 
4435
        self.assertEqual(m.additional, [])
 
4436
 
 
4437
 
 
4438
    def test_ednsMessageDecodeMultipleOptRecords(self):
 
4439
        """
 
4440
        An L(_EDNSMessage} instance created from a byte string containing
 
4441
        multiple I{OPT} records will discard all the C{OPT} records.
 
4442
 
 
4443
        C{ednsVersion} will be set to C{None}.
 
4444
 
 
4445
        @see: U{https://tools.ietf.org/html/rfc6891#section-6.1.1}
 
4446
        """
 
4447
        m = dns.Message()
 
4448
        m.additional = [
 
4449
            dns._OPTHeader(version=2),
 
4450
            dns._OPTHeader(version=3)]
 
4451
 
 
4452
        ednsMessage = dns._EDNSMessage()
 
4453
        ednsMessage.fromStr(m.toStr())
 
4454
 
 
4455
        self.assertEqual(ednsMessage.ednsVersion, None)
 
4456
 
 
4457
 
 
4458
    def test_fromMessageCopiesSections(self):
 
4459
        """
 
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.
 
4463
        """
 
4464
        standardMessage = dns.Message()
 
4465
        standardMessage.fromStr(MessageEDNSQuery.bytes())
 
4466
 
 
4467
        ednsMessage = dns._EDNSMessage._fromMessage(standardMessage)
 
4468
 
 
4469
        duplicates = []
 
4470
        for attrName in ('queries', 'answers', 'authority', 'additional'):
 
4471
            if (getattr(standardMessage, attrName)
 
4472
                is getattr(ednsMessage, attrName)):
 
4473
                duplicates.append(attrName)
 
4474
 
 
4475
        if duplicates:
 
4476
            self.fail(
 
4477
                'Message and _EDNSMessage shared references to the following '
 
4478
                'section lists after decoding: %s' % (duplicates,))
 
4479
 
 
4480
 
 
4481
    def test_toMessageCopiesSections(self):
 
4482
        """
 
4483
        L{dns._EDNSMessage.toStr} makes no in place changes to the message
 
4484
        instance.
 
4485
        """
 
4486
        ednsMessage = dns._EDNSMessage(ednsVersion=1)
 
4487
        ednsMessage.toStr()
 
4488
        self.assertEqual(ednsMessage.additional, [])
 
4489
 
 
4490
 
 
4491
    def test_optHeaderPosition(self):
 
4492
        """
 
4493
        L{dns._EDNSMessage} can decode OPT records, regardless of their position
 
4494
        in the additional records section.
 
4495
 
 
4496
        "The OPT RR MAY be placed anywhere within the additional data section."
 
4497
 
 
4498
        @see: U{https://tools.ietf.org/html/rfc6891#section-6.1.1}
 
4499
        """
 
4500
        # XXX: We need an _OPTHeader.toRRHeader method. See #6779.
 
4501
        b = BytesIO()
 
4502
        optRecord = dns._OPTHeader(version=1)
 
4503
        optRecord.encode(b)
 
4504
        optRRHeader = dns.RRHeader()
 
4505
        b.seek(0)
 
4506
        optRRHeader.decode(b)
 
4507
        m = dns.Message()
 
4508
        m.additional = [optRRHeader]
 
4509
 
 
4510
        actualMessages = []
 
4511
        actualMessages.append(dns._EDNSMessage._fromMessage(m).ednsVersion)
 
4512
 
 
4513
        m.additional.append(dns.RRHeader(type=dns.A))
 
4514
        actualMessages.append(
 
4515
            dns._EDNSMessage._fromMessage(m).ednsVersion)
 
4516
 
 
4517
        m.additional.insert(0, dns.RRHeader(type=dns.A))
 
4518
        actualMessages.append(
 
4519
            dns._EDNSMessage._fromMessage(m).ednsVersion)
 
4520
 
 
4521
        self.assertEqual(
 
4522
            [1] * 3,
 
4523
            actualMessages
 
4524
        )
 
4525
 
 
4526
 
 
4527
    def test_ednsDecode(self):
 
4528
        """
 
4529
        The L(_EDNSMessage} instance created by L{dns._EDNSMessage.fromStr}
 
4530
        derives its edns specific values (C{ednsVersion}, etc) from the supplied
 
4531
        OPT record.
 
4532
        """
 
4533
        m = self.messageFactory()
 
4534
        m.fromStr(MessageEDNSComplete.bytes())
 
4535
 
 
4536
        self.assertEqual(m, self.messageFactory(**MessageEDNSComplete.kwargs()))
 
4537
 
 
4538
 
 
4539
    def test_ednsEncode(self):
 
4540
        """
 
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.
 
4544
        """
 
4545
        self.assertEqual(
 
4546
            self.messageFactory(**MessageEDNSComplete.kwargs()).toStr(),
 
4547
            MessageEDNSComplete.bytes())
 
4548
 
 
4549
 
 
4550
    def test_extendedRcodeEncode(self):
 
4551
        """
 
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.
 
4555
        """
 
4556
        self.assertEqual(
 
4557
            self.messageFactory(**MessageEDNSExtendedRCODE.kwargs()).toStr(),
 
4558
            MessageEDNSExtendedRCODE.bytes())
 
4559
 
 
4560
 
 
4561
    def test_extendedRcodeDecode(self):
 
4562
        """
 
4563
        The L(_EDNSMessage} instance created by L{dns._EDNSMessage.fromStr}
 
4564
        derives RCODE from the supplied OPT record.
 
4565
        """
 
4566
        m = self.messageFactory()
 
4567
        m.fromStr(MessageEDNSExtendedRCODE.bytes())
 
4568
 
 
4569
        self.assertEqual(
 
4570
            m, self.messageFactory(**MessageEDNSExtendedRCODE.kwargs()))
 
4571
 
 
4572
 
 
4573
    def test_extendedRcodeZero(self):
 
4574
        """
 
4575
        Note that EXTENDED-RCODE value 0 indicates that an unextended RCODE is
 
4576
        in use (values 0 through 15).
 
4577
 
 
4578
        https://tools.ietf.org/html/rfc6891#section-6.1.3
 
4579
        """
 
4580
        ednsMessage = self.messageFactory(rCode=15, ednsVersion=0)
 
4581
        standardMessage = ednsMessage._toMessage()
 
4582
 
 
4583
        self.assertEqual(
 
4584
            (15, 0),
 
4585
            (standardMessage.rCode, standardMessage.additional[0].extendedRCODE)
 
4586
        )
 
4587
 
 
4588
 
 
4589
 
 
4590
class ResponseFromMessageTests(unittest.SynchronousTestCase):
 
4591
    """
 
4592
    Tests for L{dns._responseFromMessage}.
 
4593
    """
 
4594
    def test_responseFromMessageResponseType(self):
 
4595
        """
 
4596
        L{dns.Message._responseFromMessage} is a constructor function which
 
4597
        generates a new I{answer} message from an existing L{dns.Message} like
 
4598
        instance.
 
4599
        """
 
4600
        request = dns.Message()
 
4601
        response = dns._responseFromMessage(responseConstructor=dns.Message,
 
4602
                                            message=request)
 
4603
        self.assertIsNot(request, response)
 
4604
 
 
4605
 
 
4606
    def test_responseType(self):
 
4607
        """
 
4608
        L{dns._responseFromMessage} returns a new instance of C{cls}
 
4609
        """
 
4610
        class SuppliedClass(object):
 
4611
            id = 1
 
4612
            queries = []
 
4613
 
 
4614
        expectedClass = dns.Message
 
4615
 
 
4616
        self.assertIsInstance(
 
4617
            dns._responseFromMessage(responseConstructor=expectedClass,
 
4618
                                     message=SuppliedClass()),
 
4619
            expectedClass
 
4620
        )
 
4621
 
 
4622
 
 
4623
    def test_responseId(self):
 
4624
        """
 
4625
        L{dns._responseFromMessage} copies the C{id} attribute of the original
 
4626
        message.
 
4627
        """
 
4628
        self.assertEqual(
 
4629
            1234,
 
4630
            dns._responseFromMessage(responseConstructor=dns.Message,
 
4631
                                     message=dns.Message(id=1234)).id
 
4632
        )
 
4633
 
 
4634
 
 
4635
    def test_responseAnswer(self):
 
4636
        """
 
4637
        L{dns._responseFromMessage} sets the C{answer} flag to L{True}
 
4638
        """
 
4639
        request = dns.Message()
 
4640
        response = dns._responseFromMessage(responseConstructor=dns.Message,
 
4641
                                            message=request)
 
4642
        self.assertEqual(
 
4643
            (False, True),
 
4644
            (request.answer, response.answer)
 
4645
        )
 
4646
 
 
4647
 
 
4648
    def test_responseQueries(self):
 
4649
        """
 
4650
        L{dns._responseFromMessage} copies the C{queries} attribute of the
 
4651
        original message.
 
4652
        """
 
4653
        request = dns.Message()
 
4654
        expectedQueries = [object(), object(), object()]
 
4655
        request.queries = expectedQueries[:]
 
4656
 
 
4657
        self.assertEqual(
 
4658
            expectedQueries,
 
4659
            dns._responseFromMessage(responseConstructor=dns.Message,
 
4660
                                     message=request).queries
 
4661
        )
 
4662
 
 
4663
 
 
4664
    def test_responseKwargs(self):
 
4665
        """
 
4666
        L{dns._responseFromMessage} accepts other C{kwargs} which are assigned
 
4667
        to the new message before it is returned.
 
4668
        """
 
4669
        self.assertEqual(
 
4670
            123,
 
4671
            dns._responseFromMessage(
 
4672
                responseConstructor=dns.Message, message=dns.Message(),
 
4673
                rCode=123).rCode
 
4674
        )
 
4675
 
 
4676
 
 
4677
 
 
4678
class Foo(object):
 
4679
    """
 
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}.
 
4683
    """
 
4684
    def __init__(self,
 
4685
                 field1=1, field2=2, alwaysShowField='AS',
 
4686
                 flagTrue=True, flagFalse=False, section1=None):
 
4687
        """
 
4688
        Set some flags, fields and sections as public attributes.
 
4689
        """
 
4690
        self.field1 = field1
 
4691
        self.field2 = field2
 
4692
        self.alwaysShowField = alwaysShowField
 
4693
        self.flagTrue = flagTrue
 
4694
        self.flagFalse = flagFalse
 
4695
 
 
4696
        if section1 is None:
 
4697
            section1 = []
 
4698
        self.section1 = section1
 
4699
 
 
4700
 
 
4701
    def __repr__(self):
 
4702
        """
 
4703
        Call L{dns._compactRepr} to generate a string representation.
 
4704
        """
 
4705
        return dns._compactRepr(
 
4706
            self,
 
4707
            alwaysShow='alwaysShowField'.split(),
 
4708
            fieldNames='field1 field2 alwaysShowField'.split(),
 
4709
            flagNames='flagTrue flagFalse'.split(),
 
4710
            sectionNames='section1 section2'.split()
 
4711
        )
 
4712
 
 
4713
 
 
4714
 
 
4715
class CompactReprTests(unittest.SynchronousTestCase):
 
4716
    """
 
4717
    Tests for L[dns._compactRepr}.
 
4718
    """
 
4719
    messageFactory = Foo
 
4720
    def test_defaults(self):
 
4721
        """
 
4722
        L{dns._compactRepr} omits field values and sections which have the
 
4723
        default value. Flags which are True are always shown.
 
4724
        """
 
4725
        self.assertEqual(
 
4726
            "<Foo alwaysShowField='AS' flags=flagTrue>",
 
4727
            repr(self.messageFactory())
 
4728
        )
 
4729
 
 
4730
 
 
4731
    def test_flagsIfSet(self):
 
4732
        """
 
4733
        L{dns._compactRepr} displays flags if they have a non-default value.
 
4734
        """
 
4735
        m = self.messageFactory(flagTrue=True, flagFalse=True)
 
4736
        self.assertEqual(
 
4737
            '<Foo '
 
4738
            "alwaysShowField='AS' "
 
4739
            'flags=flagTrue,flagFalse'
 
4740
            '>',
 
4741
            repr(m),
 
4742
        )
 
4743
 
 
4744
 
 
4745
    def test_nonDefautFields(self):
 
4746
        """
 
4747
        L{dns._compactRepr} displays field values if they differ from their
 
4748
        defaults.
 
4749
        """
 
4750
        m = self.messageFactory(field1=10, field2=20)
 
4751
        self.assertEqual(
 
4752
            '<Foo '
 
4753
            'field1=10 '
 
4754
            'field2=20 '
 
4755
            "alwaysShowField='AS' "
 
4756
            'flags=flagTrue'
 
4757
            '>',
 
4758
            repr(m),
 
4759
        )
 
4760
 
 
4761
 
 
4762
    def test_nonDefaultSections(self):
 
4763
        """
 
4764
        L{dns._compactRepr} displays sections which differ from their defaults.
 
4765
        """
 
4766
        m = self.messageFactory()
 
4767
        m.section1 = [1, 1, 1]
 
4768
        m.section2 = [2, 2, 2]
 
4769
        self.assertEqual(
 
4770
            '<Foo '
 
4771
            "alwaysShowField='AS' "
 
4772
            'flags=flagTrue '
 
4773
            'section1=[1, 1, 1] '
 
4774
            'section2=[2, 2, 2]'
 
4775
            '>',
 
4776
            repr(m),
 
4777
        )