示例#1
0
class GenericInterfaceTests(unittest.TestCase):
    def setUp(self):
        # Dummy client for testing - we're not going to connect that bootstrap broker
        self.client = Client(broker_list='broker1.example.com:9091,broker2.example.com:9092')
        self.client._connected = True
        self.metadata_response = topic_metadata()

    def test_close(self):
        # Two brokers for the client
        broker = Broker('host1.example.com', id=1, port=8031)
        broker.rack = 'rack1'
        broker.close = MagicMock()
        self.client.cluster.add_broker(broker)

        broker = Broker('host2.example.com', id=101, port=8032)
        broker.rack = 'rack1'
        broker.close = MagicMock()
        self.client.cluster.add_broker(broker)

        self.client.close()
        for broker_id in self.client.cluster.brokers:
            self.client.cluster.brokers[broker_id].close.assert_called_once()

    def test_create(self):
        assert self.client.configuration.broker_list == [('broker1.example.com', 9091), ('broker2.example.com', 9092)]

    def test_create_with_configuration(self):
        config = ClientConfiguration(zkconnect='zk.example.com:2181/kafka-cluster')
        client = Client(configuration=config)
        assert client.configuration == config

    def test_create_config_zkconnect(self):
        test_client = Client(zkconnect='zk.example.com:2181/kafka-cluster')
        assert test_client.configuration.zkconnect == 'zk.example.com:2181/kafka-cluster'

    def test_create_config_bad_arg(self):
        self.assertRaises(ConfigurationError, Client, invalidconfig='foo')

    def test_create_config_bad_config_object(self):
        self.assertRaises(ConfigurationError, Client, configuration='foo')

    @patch.object(Cluster, 'create_from_zookeeper')
    def test_connect_zookeeper(self, mock_create):
        mock_create.return_value = Cluster()
        test_client = Client(zkconnect='zk.example.com:2181/kafka-cluster')
        test_client.connect()
        mock_create.assert_called_once_with(zkconnect='zk.example.com:2181/kafka-cluster', fetch_topics=False)

    @patch.object(Broker, 'connect')
    @patch.object(Broker, 'send')
    @patch.object(Broker, 'close')
    def test_connect_broker_list(self, mock_close, mock_send, mock_connect):
        def add_brokers_with_mocks(metadata):
            self.client._update_brokers_from_metadata(metadata)
            for broker_id in self.client.cluster.brokers:
                self.client.cluster.brokers[broker_id].connect = MagicMock()

        mock_connect.side_effect = [ConnectionError, None]
        mock_send.return_value = (1, self.metadata_response)
        self.client._update_from_metadata = MagicMock()
        self.client._update_from_metadata.side_effect = add_brokers_with_mocks

        self.client.connect()
        mock_connect.assert_has_calls([call(), call()])
        mock_send.assert_called_once()
        assert isinstance(mock_send.call_args[0][0], TopicMetadataV1Request)
        mock_close.assert_called_once()

        # Metadata is updated and brokers are connected
        self.client._update_from_metadata.assert_called_once_with(self.metadata_response)
        for broker_id in self.client.cluster.brokers:
            self.client.cluster.brokers[broker_id].connect.assert_called_once()

    def test_connect_broker_list_exhausted(self):
        self.client._maybe_bootstrap_cluster = MagicMock()
        self.client._maybe_bootstrap_cluster.return_value = False
        self.assertRaises(ConnectionError, self.client.connect)
示例#2
0
class TopicsTests(unittest.TestCase):
    def setUp(self):
        # Dummy client for testing - we're not going to connect that bootstrap broker
        self.client = Client()
        self.metadata_response = topic_metadata()

    def test_maybe_update_full_metadata_expired(self):
        self.client._send_any_broker = MagicMock()
        self.client._send_any_broker.return_value = 'metadata_response'
        self.client._update_from_metadata = MagicMock()

        fake_last_time = time.time() - (self.client.configuration.metadata_refresh * 2)
        self.client._last_full_metadata = fake_last_time
        self.client._maybe_update_full_metadata()

        assert self.client._last_full_metadata > fake_last_time
        self.client._send_any_broker.assert_called_once()
        arg = self.client._send_any_broker.call_args[0][0]
        assert isinstance(arg, TopicMetadataV1Request)
        assert arg['topics'] is None
        self.client._update_from_metadata.assert_called_once_with('metadata_response', delete=True)

    def test_maybe_update_full_metadata_nocache(self):
        self.client._send_any_broker = MagicMock()
        self.client._update_from_metadata = MagicMock()

        fake_last_time = time.time() - 1
        self.client._last_full_metadata = fake_last_time
        self.client._maybe_update_full_metadata(cache=False)

        assert self.client._last_full_metadata > fake_last_time

    def test_maybe_update_full_metadata_usecache(self):
        self.client._send_any_broker = MagicMock()
        self.client._update_from_metadata = MagicMock()

        fake_last_time = time.time() - 1
        self.client._last_full_metadata = fake_last_time
        self.client._maybe_update_full_metadata(cache=True)

        assert self.client._last_full_metadata == fake_last_time

    def test_maybe_update_metadata_for_topics_noupdate(self):
        self.client._update_from_metadata(self.metadata_response)
        self.client.cluster.topics['topic1']._last_updated = time.time()

        self.client._update_from_metadata = MagicMock()
        self.client._send_any_broker = MagicMock()
        self.client._maybe_update_metadata_for_topics(['topic1'])
        self.client._update_from_metadata.assert_not_called()

    def test_maybe_update_metadata_for_topics_expired(self):
        self.client._update_from_metadata(self.metadata_response)
        self.client.cluster.topics['topic1']._last_updated = 100

        self.client._update_from_metadata = MagicMock()
        self.client._send_any_broker = MagicMock()
        self.client._maybe_update_metadata_for_topics(['topic1'])
        self.client._update_from_metadata.assert_called_once()
        req = self.client._send_any_broker.call_args[0][0]
        assert len(req['topics']) == 1
        assert req['topics'][0] == 'topic1'

    def test_maybe_update_metadata_for_topics_forced(self):
        self.client._update_from_metadata(self.metadata_response)
        self.client.cluster.topics['topic1']._last_updated = time.time()

        self.client._update_from_metadata = MagicMock()
        self.client._send_any_broker = MagicMock()
        self.client._maybe_update_metadata_for_topics(['topic1'], cache=False)
        self.client._update_from_metadata.assert_called_once()
        req = self.client._send_any_broker.call_args[0][0]
        assert len(req['topics']) == 1
        assert req['topics'][0] == 'topic1'

    def test_maybe_update_metadata_for_topics_nonexistent(self):
        self.client._update_from_metadata(self.metadata_response)
        self.client.cluster.topics['topic1']._last_updated = time.time()

        self.client._update_from_metadata = MagicMock()
        self.client._send_any_broker = MagicMock()
        self.client._maybe_update_metadata_for_topics(['topic1', 'topic2'])
        self.client._update_from_metadata.assert_called_once()
        req = self.client._send_any_broker.call_args[0][0]
        assert len(req['topics']) == 2
        assert req['topics'][0] == 'topic1'
        assert req['topics'][1] == 'topic2'

    def test_update_from_metadata(self):
        self.client._update_brokers_from_metadata = MagicMock()
        self.client._update_topics_from_metadata = MagicMock()

        self.client._update_from_metadata('fake_metadata')
        self.client._update_brokers_from_metadata.assert_called_once_with('fake_metadata')
        self.client._update_topics_from_metadata.assert_called_once_with('fake_metadata', delete=False)

    def test_update_topics_from_metadata_create(self):
        # Don't want to test the broker update code here
        self.client.cluster.add_broker(Broker('host1.example.com', id=1, port=8031))
        self.client.cluster.add_broker(Broker('host2.example.com', id=101, port=8032))

        self.client._update_topics_from_metadata(self.metadata_response)
        assert_cluster_has_topics(self.client.cluster, self.metadata_response)

    def test_update_topics_from_metadata_missing_broker(self):
        # Don't want to test the broker update code here
        self.client.cluster.add_broker(Broker('host1.example.com', id=1, port=8031))

        self.client._update_topics_from_metadata(self.metadata_response)
        assert_cluster_has_topics(self.client.cluster, self.metadata_response)
        assert 101 in self.client.cluster.brokers
        assert self.client.cluster.brokers[101].endpoint.hostname is None

    def test_maybe_delete_topics_not_in_metadata(self):
        # Don't want to test the broker update code here
        broker1 = Broker('host1.example.com', id=1, port=8031)
        broker2 = Broker('host2.example.com', id=101, port=8032)
        topic = Topic('topic1', 1)
        self.client.cluster.add_broker(broker1)
        self.client.cluster.add_broker(broker2)
        self.client.cluster.add_topic(topic)
        topic.partitions[0].add_replica(broker2)
        topic.partitions[0].add_replica(broker1)
        topic = Topic('topic2', 1)
        self.client.cluster.add_broker(broker1)
        self.client.cluster.add_broker(broker2)
        self.client.cluster.add_topic(topic)
        topic.partitions[0].add_replica(broker2)
        topic.partitions[0].add_replica(broker1)

        self.client._maybe_delete_topics_not_in_metadata(self.metadata_response, delete=True)
        assert 'topic2' not in self.client.cluster.topics
        assert 'topic1' in self.client.cluster.topics

    def test_update_topics_from_metadata_update_replicas(self):
        # Don't want to test the broker update code here
        broker1 = Broker('host1.example.com', id=1, port=8031)
        broker2 = Broker('host2.example.com', id=101, port=8032)
        broker3 = Broker('host3.example.com', id=304, port=8033)
        topic = Topic('topic1', 2)
        self.client.cluster.add_broker(broker1)
        self.client.cluster.add_broker(broker2)
        self.client.cluster.add_broker(broker3)
        self.client.cluster.add_topic(topic)
        topic.partitions[0].add_replica(broker3)
        topic.partitions[0].add_replica(broker1)
        topic.partitions[1].add_replica(broker2)
        topic.partitions[1].add_replica(broker1)

        self.client._update_topics_from_metadata(self.metadata_response)
        assert_cluster_has_topics(self.client.cluster, self.metadata_response)

    def test_update_topics_from_metadata_delete_replicas(self):
        # Don't want to test the broker update code here
        broker1 = Broker('host1.example.com', id=1, port=8031)
        broker2 = Broker('host2.example.com', id=101, port=8032)
        broker3 = Broker('host3.example.com', id=304, port=8033)
        topic = Topic('topic1', 2)
        self.client.cluster.add_broker(broker1)
        self.client.cluster.add_broker(broker2)
        self.client.cluster.add_broker(broker3)
        self.client.cluster.add_topic(topic)
        topic.partitions[0].add_replica(broker2)
        topic.partitions[0].add_replica(broker1)
        topic.partitions[0].add_replica(broker3)
        topic.partitions[1].add_replica(broker2)
        topic.partitions[1].add_replica(broker1)

        self.client._update_topics_from_metadata(self.metadata_response)
        assert_cluster_has_topics(self.client.cluster, self.metadata_response)

    def test_update_brokers_from_metadata(self):
        self.client._update_brokers_from_metadata(self.metadata_response)
        assert_cluster_has_brokers(self.client.cluster, self.metadata_response)

    def test_update_brokers_from_metadata_update_rack(self):
        broker1 = Broker('host1.example.com', id=1, port=8031)
        broker1.rack = 'wrongrack'
        self.client.cluster.add_broker(broker1)

        self.client._update_brokers_from_metadata(self.metadata_response)
        assert_cluster_has_brokers(self.client.cluster, self.metadata_response)

    def test_update_brokers_from_metadata_update_host(self):
        broker1 = Broker('wronghost.example.com', id=1, port=8031)
        self.client.cluster.add_broker(broker1)
        broker1.close = MagicMock()

        self.client._update_brokers_from_metadata(self.metadata_response)
        assert_cluster_has_brokers(self.client.cluster, self.metadata_response)
        broker1.close.assert_called_once()

    def test_map_topic_partitions_to_brokers(self):
        self.client._update_from_metadata(self.metadata_response)
        val = self.client._map_topic_partitions_to_brokers(['topic1'])
        assert val == {1: {'topic1': [0]}, 101: {'topic1': [1]}}

    def test_map_topic_partitions_to_brokers_nonexistent(self):
        self.client._update_from_metadata(self.metadata_response)
        self.assertRaises(TopicError, self.client._map_topic_partitions_to_brokers, ['nosuchtopic'])
示例#3
0
class GenericInterfaceTests(unittest.TestCase):
    def setUp(self):
        # Dummy client for testing - we're not going to connect that bootstrap broker
        self.client = Client(
            broker_list='broker1.example.com:9091,broker2.example.com:9092')
        self.client._connected = True
        self.metadata_response = topic_metadata()

    def test_close(self):
        # Two brokers for the client
        broker = Broker('host1.example.com', id=1, port=8031)
        broker.rack = 'rack1'
        broker.close = MagicMock()
        self.client.cluster.add_broker(broker)

        broker = Broker('host2.example.com', id=101, port=8032)
        broker.rack = 'rack1'
        broker.close = MagicMock()
        self.client.cluster.add_broker(broker)

        self.client.close()
        for broker_id in self.client.cluster.brokers:
            self.client.cluster.brokers[broker_id].close.assert_called_once()

    def test_create(self):
        assert self.client.configuration.broker_list == [
            ('broker1.example.com', 9091), ('broker2.example.com', 9092)
        ]

    def test_create_with_configuration(self):
        config = ClientConfiguration(
            zkconnect='zk.example.com:2181/kafka-cluster')
        client = Client(configuration=config)
        assert client.configuration == config

    def test_create_config_zkconnect(self):
        test_client = Client(zkconnect='zk.example.com:2181/kafka-cluster')
        assert test_client.configuration.zkconnect == 'zk.example.com:2181/kafka-cluster'

    def test_create_config_bad_arg(self):
        self.assertRaises(ConfigurationError, Client, invalidconfig='foo')

    def test_create_config_bad_config_object(self):
        self.assertRaises(ConfigurationError, Client, configuration='foo')

    @patch.object(Cluster, 'create_from_zookeeper')
    def test_connect_zookeeper(self, mock_create):
        mock_create.return_value = Cluster()
        test_client = Client(zkconnect='zk.example.com:2181/kafka-cluster')
        test_client.connect()
        mock_create.assert_called_once_with(
            zkconnect='zk.example.com:2181/kafka-cluster', fetch_topics=False)

    @patch.object(Broker, 'connect')
    @patch.object(Broker, 'send')
    @patch.object(Broker, 'close')
    def test_connect_broker_list(self, mock_close, mock_send, mock_connect):
        def add_brokers_with_mocks(metadata):
            self.client._update_brokers_from_metadata(metadata)
            for broker_id in self.client.cluster.brokers:
                self.client.cluster.brokers[broker_id].connect = MagicMock()

        mock_connect.side_effect = [ConnectionError, None]
        mock_send.return_value = (1, self.metadata_response)
        self.client._update_from_metadata = MagicMock()
        self.client._update_from_metadata.side_effect = add_brokers_with_mocks

        self.client.connect()
        mock_connect.assert_has_calls([call(), call()])
        mock_send.assert_called_once()
        assert isinstance(mock_send.call_args[0][0], TopicMetadataV1Request)
        mock_close.assert_called_once()

        # Metadata is updated and brokers are connected
        self.client._update_from_metadata.assert_called_once_with(
            self.metadata_response)
        for broker_id in self.client.cluster.brokers:
            self.client.cluster.brokers[broker_id].connect.assert_called_once()

    def test_connect_broker_list_exhausted(self):
        self.client._maybe_bootstrap_cluster = MagicMock()
        self.client._maybe_bootstrap_cluster.return_value = False
        self.assertRaises(ConnectionError, self.client.connect)