def test_close(self):
     proc = psutil.Process()
     ip_addresses = {
         info[4][0]
         for info in
         socket.getaddrinfo('example.com', 80, socket.AF_INET,
                            socket.SOCK_DGRAM, socket.IPPROTO_IP)
     }
     self.assertGreater(len(ip_addresses), 0)
     protocol = Protocol(
         config=Configuration(service_endpoint='http://example.com',
                              credentials=Credentials('A', 'B'),
                              auth_type=NOAUTH,
                              version=Version(Build(15, 1)),
                              retry_policy=FailFast()))
     session = protocol.get_session()
     session.get('http://example.com')
     self.assertEqual(
         len({
             p.raddr[0]
             for p in proc.connections() if p.raddr[0] in ip_addresses
         }), 1)
     protocol.release_session(session)
     protocol.close()
     self.assertEqual(
         len({
             p.raddr[0]
             for p in proc.connections() if p.raddr[0] in ip_addresses
         }), 0)
Beispiel #2
0
    def test_unsupported_fields(self):
        # Create a field that is not supported by any current versions. Test that we fail when using this field
        class UnsupportedProp(ExtendedProperty):
            property_set_id = 'deadcafe-beef-beef-beef-deadcafebeef'
            property_name = 'Unsupported Property'
            property_type = 'String'

        attr_name = 'unsupported_property'
        self.ITEM_CLASS.register(attr_name=attr_name, attr_cls=UnsupportedProp)
        try:
            for f in self.ITEM_CLASS.FIELDS:
                if f.name == attr_name:
                    f.supported_from = Build(99, 99, 99, 99)

            with self.assertRaises(ValueError):
                self.test_folder.get(**{attr_name: 'XXX'})
            with self.assertRaises(ValueError):
                list(self.test_folder.filter(**{attr_name: 'XXX'}))
            with self.assertRaises(ValueError):
                list(self.test_folder.all().only(attr_name))
            with self.assertRaises(ValueError):
                list(self.test_folder.all().values(attr_name))
            with self.assertRaises(ValueError):
                list(self.test_folder.all().values_list(attr_name))
        finally:
            self.ITEM_CLASS.deregister(attr_name=attr_name)
Beispiel #3
0
 def test_decrease_poolsize(self):
     # Test increasing and decreasing the pool size
     max_connections = 3
     protocol = Protocol(config=Configuration(
         service_endpoint='https://example.com/Foo.asmx',
         credentials=Credentials(get_random_string(8), get_random_string(
             8)),
         auth_type=NTLM,
         version=Version(Build(15, 1)),
         retry_policy=FailFast(),
         max_connections=max_connections,
     ))
     self.assertEqual(protocol._session_pool.qsize(), 0)
     self.assertEqual(protocol.session_pool_size, 0)
     protocol.increase_poolsize()
     protocol.increase_poolsize()
     protocol.increase_poolsize()
     with self.assertRaises(SessionPoolMaxSizeReached):
         protocol.increase_poolsize()
     self.assertEqual(protocol._session_pool.qsize(), max_connections)
     self.assertEqual(protocol.session_pool_size, max_connections)
     protocol.decrease_poolsize()
     protocol.decrease_poolsize()
     with self.assertRaises(SessionPoolMinSizeReached):
         protocol.decrease_poolsize()
     self.assertEqual(protocol._session_pool.qsize(), 1)
Beispiel #4
0
    def test_protocol_instance_caching(self, m):
        # Verify that we get the same Protocol instance for the same combination of (endpoint, credentials)
        user, password = get_random_string(8), get_random_string(8)
        config = Configuration(service_endpoint='https://example.com/Foo.asmx',
                               credentials=Credentials(user, password),
                               auth_type=NTLM,
                               version=Version(Build(15, 1)),
                               retry_policy=FailFast())

        # Test CachingProtocol.__getitem__
        with self.assertRaises(KeyError):
            _ = Protocol[config]
        base_p = Protocol(config=config)
        self.assertEqual(base_p, Protocol[config][0])

        # Make sure we always return the same item when creating a Protocol with the same endpoint and creds
        for _ in range(10):
            p = Protocol(config=config)
            self.assertEqual(base_p, p)
            self.assertEqual(id(base_p), id(p))
            self.assertEqual(hash(base_p), hash(p))
            self.assertEqual(id(base_p._session_pool), id(p._session_pool))

        # Test CachingProtocol.__delitem__
        del Protocol[config]
        with self.assertRaises(KeyError):
            _ = Protocol[config]

        # Make sure we get a fresh instance after we cleared the cache
        p = Protocol(config=config)
        self.assertNotEqual(base_p, p)

        Protocol.clear_cache()
Beispiel #5
0
 def test_api_version(self):
     self.assertEqual(Build(8, 0).api_version(), 'Exchange2007')
     self.assertEqual(Build(8, 1).api_version(), 'Exchange2007_SP1')
     self.assertEqual(Build(8, 2).api_version(), 'Exchange2007_SP1')
     self.assertEqual(Build(8, 3).api_version(), 'Exchange2007_SP1')
     self.assertEqual(Build(15, 0, 1, 1).api_version(), 'Exchange2013')
     self.assertEqual(Build(15, 0, 1, 1).api_version(), 'Exchange2013')
     self.assertEqual(
         Build(15, 0, 847, 0).api_version(), 'Exchange2013_SP1')
     with self.assertRaises(ValueError):
         Build(16, 0).api_version()
     with self.assertRaises(ValueError):
         Build(15, 4).api_version()
Beispiel #6
0
    def test_protocol_instance_caching(self, m):
        # Verify that we get the same Protocol instance for the same combination of (endpoint, credentials)
        m.get('https://example.com/EWS/types.xsd', status_code=200)
        base_p = Protocol(config=Configuration(
            service_endpoint='https://example.com/Foo.asmx', credentials=Credentials('A', 'B'),
            auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
        ))

        for i in range(10):
            p = Protocol(config=Configuration(
                service_endpoint='https://example.com/Foo.asmx', credentials=Credentials('A', 'B'),
                auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
            ))
            self.assertEqual(base_p, p)
            self.assertEqual(id(base_p), id(p))
            self.assertEqual(hash(base_p), hash(p))
            self.assertEqual(id(base_p._session_pool), id(p._session_pool))
Beispiel #7
0
    def test_protocol_instance_caching(self, m):
        # Verify that we get the same Protocol instance for the same combination of (endpoint, credentials)
        user, password = get_random_string(8), get_random_string(8)
        base_p = Protocol(config=Configuration(
            service_endpoint='https://example.com/Foo.asmx', credentials=Credentials(user, password),
            auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
        ))

        for _ in range(10):
            p = Protocol(config=Configuration(
                service_endpoint='https://example.com/Foo.asmx', credentials=Credentials(user, password),
                auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
            ))
            self.assertEqual(base_p, p)
            self.assertEqual(id(base_p), id(p))
            self.assertEqual(hash(base_p), hash(p))
            self.assertEqual(id(base_p._session_pool), id(p._session_pool))
        Protocol.clear_cache()
Beispiel #8
0
 def test_session(self, m):
     protocol = Protocol(config=Configuration(
         service_endpoint='https://example.com/Foo.asmx',
         credentials=Credentials(get_random_string(8), get_random_string(8)),
         auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
     ))
     session = protocol.create_session()
     new_session = protocol.renew_session(session)
     self.assertNotEqual(id(session), id(new_session))
Beispiel #9
0
 def test_session(self, m):
     m.get('https://example.com/EWS/types.xsd', status_code=200)
     protocol = Protocol(config=Configuration(
         service_endpoint='https://example.com/Foo.asmx', credentials=Credentials('A', 'B'),
         auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
     ))
     session = protocol.create_session()
     new_session = protocol.renew_session(session)
     self.assertNotEqual(id(session), id(new_session))
Beispiel #10
0
 def test_invalid_build_args(self):
     with self.assertRaises(TypeError) as e:
         Build("XXX", 2, 3, 4)
     self.assertEqual(
         e.exception.args[0],
         "'major_version' 'XXX' must be of type <class 'int'>")
     with self.assertRaises(TypeError) as e:
         Build(1, "XXX", 3, 4)
     self.assertEqual(
         e.exception.args[0],
         "'minor_version' 'XXX' must be of type <class 'int'>")
     with self.assertRaises(TypeError) as e:
         Build(1, 2, "XXX", 4)
     self.assertEqual(e.exception.args[0],
                      "'major_build' 'XXX' must be of type <class 'int'>")
     with self.assertRaises(TypeError) as e:
         Build(1, 2, 3, "XXX")
     self.assertEqual(e.exception.args[0],
                      "'minor_build' 'XXX' must be of type <class 'int'>")
Beispiel #11
0
 def test_hardcode_all(self, m):
     # Test that we can hardcode everything without having a working server. This is useful if neither tasting or
     # guessing missing values works.
     Configuration(
         server="example.com",
         credentials=Credentials(get_random_string(8),
                                 get_random_string(8)),
         auth_type=NTLM,
         version=Version(build=Build(15, 1, 2, 3), api_version="foo"),
     )
Beispiel #12
0
 def test_magic(self):
     config = Configuration(
         server="example.com",
         credentials=Credentials(get_random_string(8),
                                 get_random_string(8)),
         auth_type=NTLM,
         version=Version(build=Build(15, 1, 2, 3), api_version="foo"),
     )
     # Just test that these work
     str(config)
     repr(config)
Beispiel #13
0
    def test_q(self):
        version = Version(build=EXCHANGE_2007)
        account = mock_account(version=version, protocol=mock_protocol(version=version, service_endpoint='example.com'))
        root = Root(account=account)
        tz = zoneinfo.ZoneInfo('Europe/Copenhagen')
        start = datetime.datetime(2020, 9, 26, 8, 0, 0, tzinfo=tz)
        end = datetime.datetime(2020, 9, 26, 11, 0, 0, tzinfo=tz)
        result = '''\
<m:Restriction xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
    <t:And xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
        <t:Or>
            <t:Contains ContainmentMode="Substring" ContainmentComparison="Exact">
                <t:FieldURI FieldURI="item:Categories"/>
                <t:Constant Value="FOO"/>
            </t:Contains>
            <t:Contains ContainmentMode="Substring" ContainmentComparison="Exact">
                <t:FieldURI FieldURI="item:Categories"/>
                <t:Constant Value="BAR"/>
            </t:Contains>
        </t:Or>
        <t:IsGreaterThan>
            <t:FieldURI FieldURI="calendar:End"/>
            <t:FieldURIOrConstant>
                <t:Constant Value="2020-09-26T08:00:00+02:00"/>
            </t:FieldURIOrConstant>
        </t:IsGreaterThan>
        <t:IsLessThan>
            <t:FieldURI FieldURI="calendar:Start"/>
            <t:FieldURIOrConstant>
                <t:Constant Value="2020-09-26T11:00:00+02:00"/>
            </t:FieldURIOrConstant>
        </t:IsLessThan>
    </t:And>
</m:Restriction>'''
        q = Q(Q(categories__contains='FOO') | Q(categories__contains='BAR'), start__lt=end, end__gt=start)
        r = Restriction(q, folders=[Calendar(root=root)], applies_to=Restriction.ITEMS)
        self.assertEqual(str(r), ''.join(s.lstrip() for s in result.split('\n')))
        # Test empty Q
        q = Q()
        self.assertEqual(q.to_xml(folders=[Calendar()], version=version, applies_to=Restriction.ITEMS), None)
        with self.assertRaises(ValueError):
            Restriction(q, folders=[Calendar(root=root)], applies_to=Restriction.ITEMS)
        # Test validation
        with self.assertRaises(ValueError):
            Q(datetime_created__range=(1,))  # Must have exactly 2 args
        with self.assertRaises(ValueError):
            Q(datetime_created__range=(1, 2, 3))  # Must have exactly 2 args
        with self.assertRaises(TypeError):
            Q(datetime_created=Build(15, 1)).clean(version=Version(build=EXCHANGE_2007))  # Must be serializable
        with self.assertRaises(ValueError):
            # Must be a timezone-aware datetime
            Q(datetime_created=datetime.datetime(2017, 1, 1)).clean(version=Version(build=EXCHANGE_2007))
        with self.assertRaises(ValueError):
            Q(categories__contains=[[1, 2], [3, 4]]).clean(version=Version(build=EXCHANGE_2007))  # Must be single value
Beispiel #14
0
 def test_pickle(self):
     # Test that we can pickle, repr and str Protocols
     o = Protocol(config=Configuration(
         service_endpoint='https://example.com/Foo.asmx',
         credentials=Credentials(get_random_string(8), get_random_string(8)),
         auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
     ))
     pickled_o = pickle.dumps(o)
     unpickled_o = pickle.loads(pickled_o)
     self.assertIsInstance(unpickled_o, type(o))
     self.assertEqual(repr(o), repr(unpickled_o))
     self.assertEqual(str(o), str(unpickled_o))
Beispiel #15
0
 def get_test_protocol(**kwargs):
     return Protocol(config=Configuration(
         server=kwargs.get("server"),
         service_endpoint=kwargs.get(
             "service_endpoint",
             f"https://{get_random_hostname()}/Foo.asmx"),
         credentials=kwargs.get(
             "credentials",
             Credentials(get_random_string(8), get_random_string(8))),
         auth_type=kwargs.get("auth_type", NTLM),
         version=kwargs.get("version", Version(Build(15, 1))),
         retry_policy=kwargs.get("retry_policy", FailFast()),
         max_connections=kwargs.get("max_connections"),
     ))
Beispiel #16
0
    def test_close(self):
        # Don't use example.com here - it does not resolve or answer on all ISPs
        proc = psutil.Process()
        ip_addresses = {
            info[4][0]
            for info in
            socket.getaddrinfo('httpbin.org', 80, socket.AF_INET,
                               socket.SOCK_DGRAM, socket.IPPROTO_IP)
        }

        def conn_count():
            return len(
                [p for p in proc.connections() if p.raddr[0] in ip_addresses])

        self.assertGreater(len(ip_addresses), 0)
        protocol = Protocol(config=Configuration(
            service_endpoint='http://httpbin.org',
            credentials=Credentials(get_random_string(8), get_random_string(
                8)),
            auth_type=NOAUTH,
            version=Version(Build(15, 1)),
            retry_policy=FailFast(),
            max_connections=3))
        # Merely getting a session should not create conections
        session = protocol.get_session()
        self.assertEqual(conn_count(), 0)
        # Open one URL - we have 1 connection
        session.get('http://httpbin.org')
        self.assertEqual(conn_count(), 1)
        # Open the same URL - we should still have 1 connection
        session.get('http://httpbin.org')
        self.assertEqual(conn_count(), 1)

        # Open some more connections
        s2 = protocol.get_session()
        s2.get('http://httpbin.org')
        s3 = protocol.get_session()
        s3.get('http://httpbin.org')
        self.assertEqual(conn_count(), 3)

        # Releasing the sessions does not close the connections
        protocol.release_session(session)
        protocol.release_session(s2)
        protocol.release_session(s3)
        self.assertEqual(conn_count(), 3)

        # But closing explicitly does
        protocol.close()
        self.assertEqual(conn_count(), 0)
Beispiel #17
0
 def test_decrease_poolsize(self):
     protocol = Protocol(config=Configuration(
         service_endpoint='https://example.com/Foo.asmx', credentials=Credentials('A', 'B'),
         auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
     ))
     self.assertEqual(protocol._session_pool.qsize(), Protocol.SESSION_POOLSIZE)
     protocol.decrease_poolsize()
     self.assertEqual(protocol._session_pool.qsize(), 3)
     protocol.decrease_poolsize()
     self.assertEqual(protocol._session_pool.qsize(), 2)
     protocol.decrease_poolsize()
     self.assertEqual(protocol._session_pool.qsize(), 1)
     with self.assertRaises(SessionPoolMinSizeReached):
         protocol.decrease_poolsize()
     self.assertEqual(protocol._session_pool.qsize(), 1)
Beispiel #18
0
 def test_invalid_version_args(self):
     with self.assertRaises(TypeError) as e:
         Version(build="XXX")
     self.assertEqual(
         e.exception.args[0],
         "'build' 'XXX' must be of type <class 'exchangelib.version.Build'>"
     )
     with self.assertRaises(TypeError) as e:
         Version(build="XXX", api_version="XXX")
     self.assertEqual(
         e.exception.args[0],
         "'build' 'XXX' must be of type <class 'exchangelib.version.Build'>"
     )
     with self.assertRaises(TypeError) as e:
         Version(build=Build(15, 1, 2, 3), api_version=999)
     self.assertEqual(e.exception.args[0],
                      "'api_version' 999 must be of type <class 'str'>")
Beispiel #19
0
    def test_from_response(self, m):
        # Test fallback to suggested api_version value when there is a version mismatch and response version is fishy
        version = Version.from_soap_header(
            'Exchange2007',
            to_xml(b'''\
<s:Header>
    <h:ServerVersionInfo
        MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1" Version="V2016_10_10"
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/>
</s:Header>'''))
        self.assertEqual(version.api_version, EXCHANGE_2007.api_version())
        self.assertEqual(version.api_version, 'Exchange2007')
        self.assertEqual(version.build, Build(15, 1, 845, 22))

        # Test that override the suggested version if the response version is not fishy
        version = Version.from_soap_header(
            'Exchange2013',
            to_xml(b'''\
<s:Header>
    <h:ServerVersionInfo
        MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1" Version="HELLO_FROM_EXCHANGELIB"
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/>
</s:Header>'''))
        self.assertEqual(version.api_version, 'HELLO_FROM_EXCHANGELIB')

        # Test that we override the suggested version with the version deduced from the build number if a version is not
        # present in the response
        version = Version.from_soap_header(
            'Exchange2013',
            to_xml(b'''\
<s:Header>
    <h:ServerVersionInfo
        MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1"
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/>
</s:Header>'''))
        self.assertEqual(version.api_version, 'Exchange2016')

        # Test that we use the version deduced from the build number when a version is not present in the response and
        # there was no suggested version.
        version = Version.from_soap_header(
            None,
            to_xml(b'''\
<s:Header>
    <h:ServerVersionInfo
        MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1"
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/>
</s:Header>'''))
        self.assertEqual(version.api_version, 'Exchange2016')

        # Test various parse failures
        with self.assertRaises(TransportError) as e:
            Version.from_soap_header(
                'Exchange2013',
                to_xml(b'''\
<s:Header>
    <foo/>
</s:Header>'''))
        self.assertIn('No ServerVersionInfo in header', e.exception.args[0])
        with self.assertRaises(TransportError) as e:
            Version.from_soap_header(
                'Exchange2013',
                to_xml(b'''\
<s:Header>
    <h:ServerVersionInfo MajorBuildNumber="845" MajorVersion="15" Version="V2016_10_10"
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/>
</s:Header>'''))
        self.assertIn('Bad ServerVersionInfo in response', e.exception.args[0])
Beispiel #20
0
 def test_default_api_version(self):
     # Test that a version gets a reasonable api_version value if we don't set one explicitly
     version = Version(build=Build(15, 1, 2, 3))
     self.assertEqual(version.api_version, 'Exchange2016')
Beispiel #21
0
 def test_comparison(self):
     self.assertEqual(Version(Build(15, 1, 2, 3)),
                      Version(Build(15, 1, 2, 3)))
     self.assertNotEqual(Version(Build(15, 1, 2, 3)), Version(Build(15, 1)))
     self.assertNotEqual(Version(Build(15, 1, 2, 3), api_version="XXX"),
                         Version(None, api_version="XXX"))
     self.assertNotEqual(Version(None, api_version="XXX"),
                         Version(Build(15, 1, 2), api_version="XXX"))
     self.assertEqual(Version(Build(15, 1, 2, 3), "XXX"),
                      Version(Build(15, 1, 2, 3), "XXX"))
     self.assertNotEqual(Version(Build(15, 1, 2, 3), "XXX"),
                         Version(Build(15, 1, 2, 3), "YYY"))
     self.assertNotEqual(Version(Build(15, 1, 2, 3), "XXX"),
                         Version(Build(99, 88), "XXX"))
     self.assertNotEqual(Version(Build(15, 1, 2, 3), "XXX"),
                         Version(Build(99, 88), "YYY"))
Beispiel #22
0
    def test_version_guess(self, m):
        protocol = self.get_test_protocol()
        # Test that we can get the version even on error responses
        m.post(
            protocol.service_endpoint,
            status_code=200,
            content=b"""\
<?xml version='1.0' encoding='utf-8'?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"
    MajorVersion="15" MinorVersion="1" MajorBuildNumber="2345" MinorBuildNumber="6789" Version="V2017_07_11"/>
  </s:Header>
  <s:Body>
    <m:ResolveNamesResponse
    xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
    xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:ResolveNamesResponseMessage ResponseClass="Error">
          <m:MessageText>Multiple results were found.</m:MessageText>
          <m:ResponseCode>ErrorNameResolutionMultipleResults</m:ResponseCode>
          <m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>
        </m:ResolveNamesResponseMessage>
      </m:ResponseMessages>
    </m:ResolveNamesResponse>
  </s:Body>
</s:Envelope>""",
        )
        Version.guess(protocol)
        self.assertEqual(protocol.version.build, Build(15, 1, 2345, 6789))

        # Test exception when there are no version headers
        m.post(
            protocol.service_endpoint,
            status_code=200,
            content=b"""\
<?xml version='1.0' encoding='utf-8'?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
  </s:Header>
  <s:Body>
    <m:ResolveNamesResponse
    xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
    xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:ResolveNamesResponseMessage ResponseClass="Error">
          <m:MessageText>.</m:MessageText>
          <m:ResponseCode>ErrorNameResolutionMultipleResults</m:ResponseCode>
          <m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>
        </m:ResolveNamesResponseMessage>
      </m:ResponseMessages>
    </m:ResolveNamesResponse>
  </s:Body>
</s:Envelope>""",
        )
        with self.assertRaises(TransportError) as e:
            Version.guess(protocol)
        self.assertEqual(
            e.exception.args[0],
            "No valid version headers found in response (ErrorNameResolutionMultipleResults('.'))"
        )
Beispiel #23
0
 def test_compare(self):
     self.assertEqual(Build(15, 0, 1, 2), Build(15, 0, 1, 2))
     self.assertNotEqual(Build(15, 0, 1, 2), Build(15, 0, 1, 3))
     self.assertLess(Build(15, 0, 1, 2), Build(15, 0, 1, 3))
     self.assertLess(Build(15, 0, 1, 2), Build(15, 0, 2, 2))
     self.assertLess(Build(15, 0, 1, 2), Build(15, 1, 1, 2))
     self.assertLess(Build(15, 0, 1, 2), Build(16, 0, 1, 2))
     self.assertLessEqual(Build(15, 0, 1, 2), Build(15, 0, 1, 2))
     self.assertGreater(Build(15, 0, 1, 2), Build(15, 0, 1, 1))
     self.assertGreater(Build(15, 0, 1, 2), Build(15, 0, 0, 2))
     self.assertGreater(Build(15, 1, 1, 2), Build(15, 0, 1, 2))
     self.assertGreater(Build(15, 0, 1, 2), Build(14, 0, 1, 2))
     self.assertGreaterEqual(Build(15, 0, 1, 2), Build(15, 0, 1, 2))
Beispiel #24
0
 def test_magic(self):
     with self.assertRaises(ValueError):
         Build(7, 0)
     self.assertEqual(str(Build(9, 8, 7, 6)), '9.8.7.6')