def test_default_config(self): logger_config = LoggerConfig() self.assertEqual(logging.INFO, logger_config.level) self.assertIsNone(logger_config.config_file) config = ClientConfig() config.cluster_name = self.cluster.id config.logger = logger_config client = HazelcastClient(config) self.assertEqual(logging.INFO, client.logger.level) self.assertTrue(client.logger.isEnabledFor(logging.INFO)) self.assertTrue(client.logger.isEnabledFor(logging.WARNING)) self.assertTrue(client.logger.isEnabledFor(logging.ERROR)) self.assertTrue(client.logger.isEnabledFor(logging.CRITICAL)) out = StringIO() default_handler = client.logger.handlers[0] default_handler.stream = out client.logger.debug("DEBUG_TEST") client.logger.info("INFO_TEST") client.logger.error("ERROR_TEST") client.logger.critical("CRITICAL_TEST") out.flush() out_str = out.getvalue() self.assertEqual(0, out_str.count("DEBUG_TEST")) self.assertEqual(1, out_str.count("INFO_TEST")) self.assertEqual(1, out_str.count("ERROR_TEST")) self.assertEqual(1, out_str.count("CRITICAL_TEST")) client.shutdown()
def test_client_properties_with_config_and_default_value(self): config = ClientConfig() prop = ClientProperty("key", "def-value") config.set_property(prop.name, "value") props = ClientProperties(config.get_properties()) self.assertEqual("value", props.get(prop))
def test_client_properties_get_second(self): config = ClientConfig() prop = ClientProperty("test", time_unit=TimeUnit.MILLISECOND) config.set_property(prop.name, 1000) props = ClientProperties(config.get_properties()) self.assertEqual(1, props.get_seconds(prop))
def test_client_properties_get_second_positive(self): config = ClientConfig() prop = ClientProperty("test", 1000, TimeUnit.MILLISECOND) config.set_property(prop.name, -1000) props = ClientProperties(config.get_properties()) self.assertEqual(1, props.get_seconds_positive_or_default(prop))
def test_default_logger_output(self): config = ClientConfig() config.cluster_name = self.cluster.id client = HazelcastClient(config) out = StringIO() client.logger.handlers[0].stream = out version_message = "[" + CLIENT_VERSION + "]" client.logger.info("TEST_MSG") out.flush() out_str = out.getvalue() self.assertTrue("TEST_MSG" in out_str) for line in out_str.split("\n"): if "TEST_MSG" in line: level_name, version, message = line.split(" ") self.assertEqual("INFO:", level_name) self.assertEqual(version_message, version) self.assertEqual("TEST_MSG", message) client.shutdown()
class HeartbeatTest(HazelcastTestCase): @classmethod def setUpClass(cls): configure_logging() cls.rc = cls.create_rc() @classmethod def tearDownClass(cls): cls.rc.exit() def setUp(self): self.cluster = self.create_cluster(self.rc) self.member = self.rc.startMember(self.cluster.id) self.config = ClientConfig() self.config.set_property(ClientProperties.HEARTBEAT_INTERVAL.name, 500) self.config.set_property(ClientProperties.HEARTBEAT_TIMEOUT.name, 2000) self.client = HazelcastClient(self.config) def tearDown(self): self.client.shutdown() self.rc.shutdownCluster(self.cluster.id) def test_heartbeat_stopped(self): def connection_collector(): connections = [] def collector(c): connections.append(c) collector.connections = connections return collector heartbeat_stopped_collector = connection_collector() heartbeat_restored_collector = connection_collector() self.client.heartbeat.add_listener(on_heartbeat_stopped=heartbeat_stopped_collector, on_heartbeat_restored=heartbeat_restored_collector) member2 = self.rc.startMember(self.cluster.id) addr = Address(member2.host, member2.port) open_connection_to_address(self.client, addr) self.simulate_heartbeat_lost(self.client, addr, 2) def assert_heartbeat_stopped_and_restored(): self.assertEqual(1, len(heartbeat_stopped_collector.connections)) self.assertEqual(1, len(heartbeat_restored_collector.connections)) connection_stopped = heartbeat_stopped_collector.connections[0] connection_restored = heartbeat_restored_collector.connections[0] self.assertEqual(connection_stopped._address, (member2.host, member2.port)) self.assertEqual(connection_restored._address, (member2.host, member2.port)) self.assertTrueEventually(assert_heartbeat_stopped_and_restored) @staticmethod def simulate_heartbeat_lost(client, address, timeout): client.connection_manager.connections[address].last_read_in_seconds -= timeout
def test_client_properties_set_false_when_default_is_true(self): config = ClientConfig() prop = ClientProperty("test", True) config.set_property(prop.name, False) props = ClientProperties(config.get_properties()) self.assertFalse(props.get(prop))
def test_client_properties_get_second_positive_unsupported_type(self): config = ClientConfig() prop = ClientProperty("test", "value", TimeUnit.MILLISECOND) config.set_property(prop.name, None) props = ClientProperties(config.get_properties()) with self.assertRaises(ValueError): props.get_seconds_positive_or_default(prop)
def setUp(self): self.cluster = self.create_cluster(self.rc) self.member = self.rc.startMember(self.cluster.id) self.config = ClientConfig() self.config.set_property(ClientProperties.HEARTBEAT_INTERVAL.name, 500) self.config.set_property(ClientProperties.HEARTBEAT_TIMEOUT.name, 2000) self.client = HazelcastClient(self.config)
def test_statistics_enabled(self): config = ClientConfig() config.set_property(ClientProperties.STATISTICS_ENABLED.name, True) client = HazelcastClient(config) client_uuid = client.cluster.uuid time.sleep(2 * self.DEFAULT_STATS_PERIOD) self._wait_for_statistics_collection(client_uuid) client.shutdown()
def test_custom_configuration_output(self): config = ClientConfig() config.cluster_name = self.cluster.id config_file = get_abs_path(self.CUR_DIR, "detailed_config.json") config.logger.config_file = config_file client = HazelcastClient(config) std_out = StringIO() std_err = StringIO() for handler in client.logger.handlers: if handler.get_name() == "StdoutHandler": handler.stream = std_out else: handler.stream = std_err frame_info = getframeinfo(currentframe()) client.logger.info("TEST_MSG") # These two statements above should # follow each other without a white space. # Otherwise, arrange the line number in # the assert statements accordingly. std_out.flush() std_err.flush() std_out_str = std_out.getvalue() std_err_str = std_err.getvalue() self.assertTrue("TEST_MSG" in std_out_str) self.assertTrue("TEST_MSG" in std_err_str) for line in std_out_str.split("\n"): if "TEST_MSG" in line: print(line) asc_time, name, level_name, message = line.split("*") self.assertTrue(self._is_valid_date_string(asc_time)) self.assertEqual("HazelcastClient", name) self.assertEqual("INFO", level_name) self.assertEqual("TEST_MSG", message) for line in std_err_str.split("\n"): if "TEST_MSG" in line: asc_time, name, func, line_no, level_name, message = line.split( "*") self.assertTrue(self._is_valid_date_string(asc_time)) self.assertEqual("HazelcastClient", name) self.assertEqual(frame_info.function, func) self.assertEqual(str(frame_info.lineno + 1), line_no) self.assertEqual("INFO", level_name) self.assertEqual("TEST_MSG", message) client.shutdown()
def test_client_properties_with_config_default_value_and_environment_variable( self): environ = os.environ prop = ClientProperties.HEARTBEAT_INTERVAL environ[prop.name] = "1000" config = ClientConfig() config.set_property(prop.name, 2000) props = ClientProperties(config.get_properties()) self.assertEqual(2, props.get_seconds(prop)) os.unsetenv(prop.name)
def test_statistics_disabled_by_default(self): config = ClientConfig() config.cluster_name = self.cluster.id client = HazelcastClient(config) time.sleep(2 * self.DEFAULT_STATS_PERIOD) client_uuid = client._connection_manager.client_uuid response = self._get_client_stats_from_server(client_uuid) self.assertTrue(response.success) self.assertIsNone(response.result) client.shutdown()
def test_client_only_listens(self): rc = self.create_rc() client_heartbeat_seconds = 8 cluster_config = """<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.10.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <properties> <property name="hazelcast.client.max.no.heartbeat.seconds">{}</property> </properties> </hazelcast>""".format(client_heartbeat_seconds) cluster = self.create_cluster(rc, cluster_config) member = cluster.start_member() client_config = ClientConfig() client_config.set_property(ClientProperties.HEARTBEAT_INTERVAL.name, 1000) client1 = HazelcastClient(client_config) def lifecycle_event_collector(): events = [] def event_collector(e): if e == LIFECYCLE_STATE_DISCONNECTED: events.append(e) event_collector.events = events return event_collector collector = lifecycle_event_collector() client1.lifecycle.add_listener(collector) client2 = HazelcastClient() key = "topic-name" topic = client1.get_topic(key) def message_listener(e): pass topic.add_listener(message_listener) client2topic = client2.get_topic(key) begin = time.time() while (time.time() - begin) < 2 * client_heartbeat_seconds: client2topic.publish("message") time.sleep(0.5) self.assertEqual(0, len(collector.events)) client1.shutdown() client2.shutdown() rc.exit()
def test_multiple_translators(self): config = ClientConfig() config.network_config.addresses.append("127.0.0.1:5701") config.network_config.cloud_config.enabled = True with self.assertRaises(HazelcastError): client = HazelcastClient(config)
def __init__(self, config=None): self.config = config or ClientConfig() self.properties = ClientProperties(self.config.get_properties()) self.id = HazelcastClient.CLIENT_ID.get_and_increment() self.name = self._create_client_name() self._init_logger() self._logger_extras = {"client_name": self.name, "group_name": self.config.group_config.name} self._log_group_password_info() self.lifecycle = LifecycleService(self.config, self._logger_extras) self.reactor = AsyncoreReactor(self._logger_extras) self._address_providers = self._create_address_providers() self._address_translator = self._create_address_translator() self.connection_manager = ConnectionManager(self, self.reactor.new_connection, self._address_translator) self.heartbeat = Heartbeat(self) self.invoker = InvocationService(self) self.listener = ListenerService(self) self.cluster = ClusterService(self.config, self, self._address_providers) self.partition_service = PartitionService(self) self.proxy = ProxyManager(self) self.load_balancer = RandomLoadBalancer(self.cluster) self.serialization_service = SerializationServiceV1(serialization_config=self.config.serialization_config) self.transaction_manager = TransactionManager(self) self.lock_reference_id_generator = AtomicInteger(1) self.near_cache_manager = NearCacheManager(self) self.statistics = Statistics(self) self._start()
def test_statistics_enabled_with_environment_variable(self): environ = os.environ environ[ClientProperties.STATISTICS_ENABLED.name] = "true" environ[ClientProperties.STATISTICS_PERIOD_SECONDS.name] = str(self.STATS_PERIOD) config = ClientConfig() config.cluster_name = self.cluster.id client = HazelcastClient(config) client_uuid = client._connection_manager.client_uuid time.sleep(2 * self.STATS_PERIOD) self._wait_for_statistics_collection(client_uuid) os.unsetenv(ClientProperties.STATISTICS_ENABLED.name) os.unsetenv(ClientProperties.STATISTICS_PERIOD_SECONDS.name) client.shutdown()
def test_new_id_with_at_least_one_suitable_member(self): response = self._assign_out_of_range_node_id(self.cluster.id, random.randint(0, 1)) self.assertTrueEventually( lambda: response.success and response.result is not None) config = ClientConfig() config.cluster_name = self.cluster.id config.network.smart_routing = False client = HazelcastClient(config) generator = client.get_flake_id_generator("test").blocking() for i in range(100): generator.new_id() generator.destroy() client.shutdown()
def setUp(self): configure_logging() self.rc = self.create_rc() self.cluster = self.create_cluster(self.rc, None) self.m1 = self.cluster.start_member() self.m2 = self.cluster.start_member() self.client_config = ClientConfig() self.client_config.cluster_name = self.cluster.id self.collector = event_collector()
def test_new_id_fails_when_all_members_are_out_of_node_id_range(self): response1 = self._assign_out_of_range_node_id(self.cluster.id, 0) self.assertTrueEventually( lambda: response1.success and response1.result is not None) response2 = self._assign_out_of_range_node_id(self.cluster.id, 1) self.assertTrueEventually( lambda: response2.success and response2.result is not None) config = ClientConfig() config.cluster_name = self.cluster.id client = HazelcastClient(config) generator = client.get_flake_id_generator("test").blocking() with self.assertRaises(HazelcastError): generator.new_id() generator.destroy() client.shutdown()
def __init__(self, config=None): self._context = _ClientContext() self.config = config or ClientConfig() self.properties = ClientProperties(self.config.get_properties()) self._id = HazelcastClient._CLIENT_ID.get_and_increment() self.name = self._create_client_name() self._init_logger() self._logger_extras = { "client_name": self.name, "cluster_name": self.config.cluster_name } self._reactor = AsyncoreReactor(self._logger_extras) self._serialization_service = SerializationServiceV1( serialization_config=self.config.serialization) self._near_cache_manager = NearCacheManager( self, self._serialization_service) self._internal_lifecycle_service = _InternalLifecycleService( self, self._logger_extras) self.lifecycle_service = LifecycleService( self._internal_lifecycle_service) self._invocation_service = InvocationService(self, self._reactor, self._logger_extras) self._address_provider = self._create_address_provider() self._internal_partition_service = _InternalPartitionService( self, self._logger_extras) self.partition_service = PartitionService( self._internal_partition_service) self._internal_cluster_service = _InternalClusterService( self, self._logger_extras) self.cluster_service = ClusterService(self._internal_cluster_service) self._connection_manager = ConnectionManager( self, self._reactor, self._address_provider, self._internal_lifecycle_service, self._internal_partition_service, self._internal_cluster_service, self._invocation_service, self._near_cache_manager, self._logger_extras) self._load_balancer = self._init_load_balancer(self.config) self._listener_service = ListenerService(self, self._connection_manager, self._invocation_service, self._logger_extras) self._proxy_manager = ProxyManager(self._context) self._transaction_manager = TransactionManager(self._context, self._logger_extras) self._lock_reference_id_generator = AtomicInteger(1) self._statistics = Statistics(self, self._reactor, self._connection_manager, self._invocation_service, self._near_cache_manager, self._logger_extras) self._cluster_view_listener = ClusterViewListenerService( self, self._connection_manager, self._internal_partition_service, self._internal_cluster_service, self._invocation_service) self._shutdown_lock = threading.RLock() self._init_context() self._start()
def test_client_with_cloud_discovery(self): config = ClientConfig() config.network_config.cloud_config.enabled = True config.network_config.cloud_config.discovery_token = TOKEN config.set_property( HazelcastCloudDiscovery.CLOUD_URL_BASE_PROPERTY.name, HOST + ":" + str(self.server.port)) client = TestClient(config) client._address_translator.cloud_discovery._ctx = self.ctx client._address_providers[0].cloud_discovery._ctx = self.ctx private_addresses = client._address_providers[0].load_addresses() six.assertCountEqual(self, list(ADDRESSES.keys()), private_addresses) for private_address in private_addresses: translated_address = client._address_translator.translate( private_address) self.assertEqual(ADDRESSES[private_address], translated_address)
def test_statistics_content(self): config = ClientConfig() config.cluster_name = self.cluster.id config.set_property(ClientProperties.STATISTICS_ENABLED.name, True) config.set_property(ClientProperties.STATISTICS_PERIOD_SECONDS.name, self.STATS_PERIOD) map_name = random_string() near_cache_config = NearCacheConfig(map_name) config.near_caches[map_name] = near_cache_config client = HazelcastClient(config) client_uuid = client._connection_manager.client_uuid client.get_map(map_name).blocking() time.sleep(2 * self.STATS_PERIOD) response = self._wait_for_statistics_collection(client_uuid) result = response.result.decode("utf-8") info = client._internal_cluster_service.get_local_client() local_address = "%s:%s" % (info.address.host, info.address.port) # Check near cache and client statistics self.assertEqual(1, result.count("clientName=" + client.name)) self.assertEqual(1, result.count("lastStatisticsCollectionTime=")) self.assertEqual(1, result.count("enterprise=false")) self.assertEqual(1, result.count("clientType=" + CLIENT_TYPE)) self.assertEqual(1, result.count("clientVersion=" + CLIENT_VERSION)) self.assertEqual(1, result.count("clusterConnectionTimestamp=")) self.assertEqual(1, result.count("clientAddress=" + local_address)) self.assertEqual(1, result.count("nc." + map_name + ".creationTime")) self.assertEqual(1, result.count("nc." + map_name + ".evictions")) self.assertEqual(1, result.count("nc." + map_name + ".hits")) self.assertEqual(1, result.count("nc." + map_name + ".misses")) self.assertEqual(1, result.count("nc." + map_name + ".ownedEntryCount")) self.assertEqual(1, result.count("nc." + map_name + ".expirations")) self.assertEqual(1, result.count("nc." + map_name + ".invalidations")) self.assertEqual(1, result.count("nc." + map_name + ".invalidationRequests")) self.assertEqual(1, result.count("nc." + map_name + ".ownedEntryMemoryCost")) # Check OS and runtime statistics. We cannot know what kind of statistics will be available # in different platforms. So, first try to get these statistics and then check the # response content s = Statistics(client, None, None, None, None, None) psutil_stats = s._get_os_and_runtime_stats() for stat_name in psutil_stats: self.assertEqual(1, result.count(stat_name)) client.shutdown()
def test_default_configuration_multiple_clients(self): config = ClientConfig() config.cluster_name = self.cluster.id client1 = HazelcastClient(config) client2 = HazelcastClient(config) out = StringIO() client1.logger.handlers[0].stream = out client2.logger.handlers[0].stream = out client1.logger.info("TEST_MSG") client2.logger.info("TEST_MSG") out.flush() out_str = out.getvalue() self.assertEqual(2, out_str.count("TEST_MSG")) client1.shutdown() client2.shutdown()
def test_statistics_enabled_with_negative_period(self): config = ClientConfig() config.cluster_name = self.cluster.id config.set_property(ClientProperties.STATISTICS_ENABLED.name, True) config.set_property(ClientProperties.STATISTICS_PERIOD_SECONDS.name, -1 * self.STATS_PERIOD) client = HazelcastClient(config) client_uuid = client._connection_manager.client_uuid time.sleep(2 * self.DEFAULT_STATS_PERIOD) self._wait_for_statistics_collection(client_uuid) client.shutdown()
def test_near_cache_stats(self): config = ClientConfig() config.set_property(ClientProperties.STATISTICS_ENABLED.name, True) config.set_property(ClientProperties.STATISTICS_PERIOD_SECONDS.name, self.STATS_PERIOD) map_name = random_string() near_cache_config = NearCacheConfig(map_name) config.near_cache_configs[map_name] = near_cache_config client = HazelcastClient(config) client_uuid = client.cluster.uuid test_map = client.get_map(map_name).blocking() time.sleep(2 * self.STATS_PERIOD) response = self._wait_for_statistics_collection(client_uuid) result = response.result.decode("utf-8") self.assertEqual(1, result.count("nc." + map_name + ".evictions=0")) self.assertEqual(1, result.count("nc." + map_name + ".hits=0")) self.assertEqual(1, result.count("nc." + map_name + ".misses=0")) self.assertEqual(1, result.count("nc." + map_name + ".ownedEntryCount=0")) self.assertEqual(1, result.count("nc." + map_name + ".expirations=0")) self.assertEqual(1, result.count("nc." + map_name + ".invalidations=0")) self.assertEqual( 1, result.count("nc." + map_name + ".invalidationRequests=0")) test_map.put(1, 2) # invalidation request test_map.get(1) # cache miss test_map.get(1) # cache hit test_map.put(1, 3) # invalidation + invalidation request test_map.get(1) # cache miss time.sleep(2 * self.STATS_PERIOD) response = self._wait_for_statistics_collection(client_uuid) result = response.result.decode("utf-8") self.assertEqual(1, result.count("nc." + map_name + ".evictions=0")) self.assertEqual(1, result.count("nc." + map_name + ".hits=1")) self.assertEqual(1, result.count("nc." + map_name + ".misses=2")) self.assertEqual(1, result.count("nc." + map_name + ".ownedEntryCount=1")) self.assertEqual(1, result.count("nc." + map_name + ".expirations=0")) self.assertEqual(1, result.count("nc." + map_name + ".invalidations=1")) self.assertEqual( 1, result.count("nc." + map_name + ".invalidationRequests=2")) client.shutdown()
def test_simple_custom_logging_configuration(self): logger_config = LoggerConfig() # Outputs to stdout with the level of error config_path = get_abs_path(self.CUR_DIR, "simple_config.json") logger_config.config_file = config_path self.assertEqual(config_path, logger_config.config_file) config = ClientConfig() config.cluster_name = self.cluster.id config.logger = logger_config client = HazelcastClient(config) self.assertEqual(logging.ERROR, client.logger.getEffectiveLevel()) self.assertFalse(client.logger.isEnabledFor(logging.INFO)) self.assertFalse(client.logger.isEnabledFor(logging.WARNING)) self.assertTrue(client.logger.isEnabledFor(logging.ERROR)) self.assertTrue(client.logger.isEnabledFor(logging.CRITICAL)) out = StringIO() handler = logging.getLogger("HazelcastClient").handlers[0] handler.stream = out client.logger.debug("DEBUG_TEST") client.logger.info("INFO_TEST") client.logger.error("ERROR_TEST") client.logger.critical("CRITICAL_TEST") out.flush() out_str = out.getvalue() self.assertEqual(0, out_str.count("DEBUG_TEST")) self.assertEqual(0, out_str.count("INFO_TEST")) self.assertEqual(1, out_str.count("ERROR_TEST")) self.assertEqual(1, out_str.count("CRITICAL_TEST")) client.shutdown()
def test_same_custom_configuration_file_with_multiple_clients(self): config = ClientConfig() config.cluster_name = self.cluster.id config_file = get_abs_path(self.CUR_DIR, "simple_config.json") config.logger.configuration_file = config_file client1 = HazelcastClient(config) client2 = HazelcastClient(config) out = StringIO() logging.getLogger("HazelcastClient").handlers[0].stream = out client1.logger.critical("TEST_MSG") client2.logger.critical("TEST_MSG") out.flush() out_str = out.getvalue() self.assertEqual(2, out_str.count("TEST_MSG")) client1.shutdown() client2.shutdown()
def test_statistics_disabled_with_wrong_value(self): config = ClientConfig() config.cluster_name = self.cluster.id config.set_property(ClientProperties.STATISTICS_ENABLED.name, "truee") config.set_property(ClientProperties.STATISTICS_PERIOD_SECONDS.name, self.STATS_PERIOD) client = HazelcastClient(config) client_uuid = client._connection_manager.client_uuid time.sleep(2 * self.STATS_PERIOD) response = self._get_client_stats_from_server(client_uuid) self.assertTrue(response.success) self.assertIsNone(response.result) client.shutdown()
def __init__(self, config=None): self.config = config or ClientConfig() self.lifecycle = LifecycleService(self.config) self.reactor = AsyncoreReactor() self.connection_manager = ConnectionManager( self, self.reactor.new_connection) self.heartbeat = Heartbeat(self) self.invoker = InvocationService(self) self.listener = ListenerService(self) self.cluster = ClusterService(self.config, self) self.partition_service = PartitionService(self) self.proxy = ProxyManager(self) self.load_balancer = RandomLoadBalancer(self.cluster) self.serializer = SerializationServiceV1( serialization_config=self.config.serialization_config) self.transaction_manager = TransactionManager(self) self._start()