def test_ssl_enabled_with_protocol_mismatch(self): cluster = self.create_cluster( self.rc, self.configure_cluster(self.hazelcast_ssl_xml)) cluster.start_member() # Member configured with TLSv1 with self.assertRaises(HazelcastError): HazelcastClient(**get_ssl_config( cluster.id, True, get_abs_path(self.current_directory, "server1-cert.pem"), protocol=SSLProtocol.SSLv3, ))
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_near_cache_stats(self): map_name = random_string() client = HazelcastClient( cluster_name=self.cluster.id, statistics_enabled=True, statistics_period=self.STATS_PERIOD, near_caches={ map_name: {}, }, ) client_uuid = client._connection_manager.client_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_ma_optional_server_not_authenticated(self): cluster = self.create_cluster(self.rc, self.configure_cluster(False)) cluster.start_member() with self.assertRaises(HazelcastError): HazelcastClient( **get_ssl_config( cluster.id, True, get_abs_path(self.current_directory, "server2-cert.pem"), get_abs_path(self.current_directory, "client1-cert.pem"), get_abs_path(self.current_directory, "client1-key.pem"), ) )
def test_ma_optional_client_and_server_authenticated(self): cluster = self.create_cluster(self.rc, self.configure_cluster(False)) cluster.start_member() client = HazelcastClient( **get_ssl_config( cluster.id, True, get_abs_path(self.current_directory, "server1-cert.pem"), get_abs_path(self.current_directory, "client1-cert.pem"), get_abs_path(self.current_directory, "client1-key.pem"), ) ) self.assertTrue(client.lifecycle_service.is_running()) client.shutdown()
def test_statistics_content(self): map_name = random_string() client = HazelcastClient( cluster_name=self.cluster.id, cluster_connect_timeout=30.0, statistics_enabled=True, statistics_period=self.STATS_PERIOD, near_caches={ map_name: {}, }, ) 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=" + __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 for stat_name in self.get_runtime_and_system_metrics(client): self.assertEqual(1, result.count(stat_name)) client.shutdown()
def test_statistics_period(self): client = HazelcastClient(cluster_name=self.cluster.id, statistics_enabled=True, statistics_period=self.STATS_PERIOD) client_uuid = client._connection_manager.client_uuid time.sleep(2 * self.STATS_PERIOD) response1 = self._wait_for_statistics_collection(client_uuid) time.sleep(2 * self.STATS_PERIOD) response2 = self._wait_for_statistics_collection(client_uuid) self.assertNotEqual(response1, response2) client.shutdown()
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) client = HazelcastClient() client_uuid = client.cluster.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_ma_required_client_and_server_not_authenticated(self): cluster = self.create_cluster(self.rc, self.configure_cluster(True)) member = cluster.start_member() with self.assertRaises(HazelcastError): client = HazelcastClient( get_ssl_config(True, get_abs_path(self.current_directory, "server2-cert.pem"), get_abs_path(self.current_directory, "client2-cert.pem"), get_abs_path(self.current_directory, "client2-key.pem"), protocol=PROTOCOL.TLSv1))
def test_ssl_enabled_map_size(self): cluster = self.create_cluster( self.rc, self.configure_cluster(self.hazelcast_ssl_xml)) cluster.start_member() client = HazelcastClient( get_ssl_config(True, get_abs_path(self.current_directory, "server1-cert.pem"), protocol=PROTOCOL.TLSv1)) test_map = client.get_map("test_map") fill_map(test_map, 10) self.assertEqual(test_map.size().result(), 10) client.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 test_ssl_enabled_with_custom_ciphers(self): cluster = self.create_cluster(self.rc, self.configure_cluster(self.hazelcast_ssl_xml)) cluster.start_member() client = HazelcastClient( **get_ssl_config( cluster.id, True, get_abs_path(self.current_directory, "server1-cert.pem"), ciphers="ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384", ) ) self.assertTrue(client.lifecycle_service.is_running()) client.shutdown()
def test_ma_optional_client_and_server_authenticated(self): cluster = self.create_cluster(self.rc, self.configure_cluster(False)) member = cluster.start_member() client = HazelcastClient( get_ssl_config(True, get_abs_path(self.current_directory, "server1-cert.pem"), get_abs_path(self.current_directory, "client1-cert.pem"), get_abs_path(self.current_directory, "client1-key.pem"), protocol=PROTOCOL.TLSv1)) self.assertTrue(client.lifecycle.is_live) client.shutdown()
def test_ssl_enabled_with_custom_ciphers(self): cluster = self.create_cluster( self.rc, self.configure_cluster(self.hazelcast_ssl_xml)) cluster.start_member() client = HazelcastClient( get_ssl_config( True, get_abs_path(self.current_directory, "server1-cert.pem"), protocol=PROTOCOL.TLSv1, ciphers= "DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-DES-CBC3-SHA:DHE-RSA-DES-CBC3-SHA:DHE-DSS-DES-CBC3-SHA" )) self.assertTrue(client.lifecycle.is_live) client.shutdown()
def test_ma_required_client_and_server_authenticated(self): cluster = self.create_cluster(self.rc, self.configure_cluster(True)) cluster.start_member() client = HazelcastClient( get_ssl_config(cluster.id, True, get_abs_path(self.current_directory, "server1-cert.pem"), get_abs_path(self.current_directory, "client1-cert.pem"), get_abs_path(self.current_directory, "client1-key.pem"), protocol=PROTOCOL.TLSv1)) self.assertTrue(client.lifecycle_service.is_running()) client.shutdown()
def test_statistics_period(self): config = ClientConfig() config.set_property(ClientProperties.STATISTICS_ENABLED.name, True) config.set_property(ClientProperties.STATISTICS_PERIOD_SECONDS.name, self.STATS_PERIOD) client = HazelcastClient(config) client_uuid = client.cluster.uuid time.sleep(2 * self.STATS_PERIOD) response1 = self._wait_for_statistics_collection(client_uuid) time.sleep(2 * self.STATS_PERIOD) response2 = self._wait_for_statistics_collection(client_uuid) self.assertNotEqual(response1, response2) client.shutdown()
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) client = HazelcastClient(cluster_name=self.cluster.id) generator = client.get_flake_id_generator("test").blocking() with self.assertRaises(HazelcastError): generator.new_id() generator.destroy() 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.assertTrue(response.success and response.result is not None) client = HazelcastClient(cluster_name=self.cluster.id, smart_routing=False) generator = client.get_flake_id_generator("test").blocking() for i in range(100): generator.new_id() generator.destroy() client.shutdown()
def test_near_cache_stats(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 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_metrics_blob(self): skip_if_client_version_older_than(self, "4.2.1") map_name = random_string() client = HazelcastClient( cluster_name=self.cluster.id, cluster_connect_timeout=30.0, statistics_enabled=True, statistics_period=self.STATS_PERIOD, near_caches={ map_name: {}, }, ) 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, get_metric_blob=True) result = bytearray(response.result) # We will try to decompress the blob according to its contract # to verify we have sent something that make sense pos = 2 # Skip the version dict_buf_size = BE_INT.unpack_from(result, pos)[0] pos += INT_SIZE_IN_BYTES dict_buf = result[pos:pos + dict_buf_size] self.assertTrue(len(dict_buf) > 0) pos += dict_buf_size pos += INT_SIZE_IN_BYTES # Skip metric count metrics_buf = result[pos:] self.assertTrue(len(metrics_buf) > 0) # If we are able to decompress it, we count the blob # as valid. zlib.decompress(dict_buf) zlib.decompress(metrics_buf) client.shutdown()
def test_special_characters(self): map_name = random_string() + ",t=es\\t" client = HazelcastClient(cluster_name=self.cluster.id, statistics_enabled=True, statistics_period=self.STATS_PERIOD, near_caches={ map_name: {}, }) 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") unescaped_result = self._unescape_special_chars(result) self.assertEqual(-1, result.find(map_name)) self.assertNotEqual(-1, unescaped_result.find(map_name)) client.shutdown()
def test_special_characters(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() + ",t=es\\t" 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") unescaped_result = self._unescape_special_chars(result) self.assertEqual(-1, result.find(map_name)) self.assertNotEqual(-1, unescaped_result.find(map_name)) client.shutdown()
def start(): thread_count_before = threading.active_count() parser = argparse.ArgumentParser() parser.add_argument("--hour", default=48.0, type=float, help="Duration of the test in hours") parser.add_argument( "--addresses", default="127.0.0.1", type=str, help="List of cluster member addresses separated by -", ) parser.add_argument("--log", default="default_log_file", type=str, help="Name of the log file") args = parser.parse_args() hour_limit = args.hour addresses = args.addresses log_file = args.log logging.basicConfig( filename=log_file, filemode="w", format="%(asctime)s %(message)s", datefmt="%H:%M:%S", level=logging.INFO, ) try: client = HazelcastClient( cluster_members=addresses.split("-"), data_serializable_factories={ SimpleEntryProcessor.FACTORY_ID: { SimpleEntryProcessor.CLASS_ID: SimpleEntryProcessor } }, ) except Exception: logging.exception("Client failed to start") return processor = SimpleEntryProcessor("test") test_map = client.get_map("test-map").blocking() test_map.add_entry_listener(False, added_func=listener, removed_func=listener, updated_func=listener) logging.info("Soak test operations are starting!") logging.info("* " * 20 + "\n") test_failed = [False] def run(stats): end_time = get_current_timestamp() + hour_limit * 60 * 60 while get_current_timestamp() < end_time: if test_failed[0]: return # Some other thread failed, no need to continue the test key = str(random.randint(0, ENTRY_COUNT)) value = str(random.randint(0, ENTRY_COUNT)) operation = random.randint(0, 100) try: if operation < 30: test_map.get(key) elif operation < 60: test_map.put(key, value) elif operation < 80: test_map.values(between("this", 0, 10)) else: test_map.execute_on_key(key, processor) stats.increment_operation_count() except: test_failed[0] = True logging.exception("Unexpected error occurred") return statistics = [] threads = [] thread_hang_counts = {} for i in range(THREAD_COUNT): statistic = Statistic(i) statistics.append(statistic) thread = threading.Thread(target=run, args=(statistic, )) threads.append(thread) thread_hang_counts[i] = 0 thread.start() def display_statistics(): end_time = get_current_timestamp() + hour_limit * 60 * 60 while get_current_timestamp() < end_time: time.sleep(STATS_DISPLAY_SECONDS) if test_failed[0]: # Some thread failed. No need to continue. return logging.info("-" * 40) total_ops = 0 # sum of total ops of all threads hanged_threads = [] for stat in statistics: total = stat.get_total_operation_count_and_reset( ) # per thread total_ops += total if total == 0: hanged_threads.append(stat.id) if not hanged_threads: logging.info("All threads worked without hanging") else: logging.info("%s threads hanged with ids %s", len(hanged_threads), hanged_threads) for thread_id in hanged_threads: thread_hang_counts[thread_id] += 1 logging.info("-" * 40) logging.info("Operations Per Second: %s\n", total_ops / STATS_DISPLAY_SECONDS) display_thread = threading.Thread(target=display_statistics) display_thread.start() display_thread.join() for thread in threads: thread.join() client.shutdown() logging.info("* " * 20) logging.info("Soak test has finished!") logging.info("-" * 40) if test_failed[0]: logging.info("Soak test failed!") return if sum(thread_hang_counts.values()) == 0: logging.info("All threads worked without hanging") else: for key in thread_hang_counts: hang_count = thread_hang_counts[key] if hang_count != 0: logging.info("Thread %s hanged %s times.", key, hang_count) thread_count_after = threading.active_count() logging.info("Thread count before: %s, after: %s", thread_count_before, thread_count_after)
def test_cloud_config_with_property_and_client_configuration(self): self.config.network_config.cloud_config.enabled = True self.config.set_property( ClientProperties.HAZELCAST_CLOUD_DISCOVERY_TOKEN.name, self.token) with self.assertRaises(HazelcastIllegalStateError): client = HazelcastClient(self.config)
def test_ssl_disabled(self): with self.assertRaises(HazelcastError): client = HazelcastClient(get_ssl_config(False))
def test_ssl_disabled(self): cluster = self.create_cluster(self.rc, self.configure_cluster(self.hazelcast_ssl_xml)) cluster.start_member() with self.assertRaises(HazelcastError): HazelcastClient(**get_ssl_config(cluster.id, False))