This is an automated email from the ASF dual-hosted git repository.

zhangstar333 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 7f016da4626 [fix](regression) Isolate external file cache test state 
(#69701)
7f016da4626 is described below

commit 7f016da46263748828f175f5907c18aca412de5c
Author: Gabriel <[email protected]>
AuthorDate: Wed Oct 28 11:13:24 2026 +0800

    [fix](regression) Isolate external file cache test state (#69701)
    
    ### What problem does this PR solve?
    
    The external file-cache tests depend on host disk/inode usage and
    inherited backend settings. Under resource-limit or advance-eviction
    mode, cache blocks can disappear between reads: the query-limit test
    observes an empty queue, the statistics test cannot establish stable
    hit/read counts, and the feature test times out while waiting for
    default flags to become zero.
    
    Establish a scoped baseline for these three non-concurrent suites.
    Disable upper read caches and inherited per-query limits, temporarily
    suppress advance eviction, and use 100% disk thresholds while retaining
    the failure for a genuinely full filesystem. Poll both mode flags across
    cache paths before measuring data. Restore every backend setting through
    the existing temporary-config helper, including on assertion failure.
    
    For the feature test, drive resource-limit entry with zero thresholds
    and advance-eviction entry with a one-percent threshold. A populated
    cache directory consumes an inode, whose used percentage rounds up to at
    least one. Nest threshold updates so the background monitor never
    observes an invalid enter/exit ordering during application or
    restoration. Keep the existing query results and cache assertions.
---
 .../plugins/file_cache_test_plugin.groovy          |  57 ++
 .../cache/test_file_cache_features.groovy          | 202 ++++---
 .../cache/test_file_cache_query_limit.groovy       | 586 ++++++++++-----------
 .../cache/test_file_cache_statistics.groovy        | 236 ++++-----
 4 files changed, 563 insertions(+), 518 deletions(-)

diff --git a/regression-test/plugins/file_cache_test_plugin.groovy 
b/regression-test/plugins/file_cache_test_plugin.groovy
new file mode 100644
index 00000000000..2b86153c0ee
--- /dev/null
+++ b/regression-test/plugins/file_cache_test_plugin.groovy
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import org.apache.doris.regression.suite.Suite
+
+// Use only in nonConcurrent suites: backend configuration is shared by all 
queries.
+Suite.metaClass.withStableFileCache = { Closure action ->
+    Suite suite = delegate as Suite
+    // Disable upper caches so repeated reads reach BlockFileCache.
+    suite.sql "set enable_file_cache = true"
+    suite.sql "set disable_file_cache = false"
+    suite.sql "set enable_sql_cache = false"
+    suite.sql "set enable_hive_sql_cache = false"
+    suite.sql "set enable_query_cache = false"
+    suite.sql "set enable_parquet_file_page_cache = false"
+
+    long monitorMs = 
suite.get_be_param("file_cache_background_monitor_interval_ms")
+            .values().collect { it.toLong() }.max()
+    int timeoutSeconds = Math.max(30, (monitorMs * 6L / 1000L) as int)
+    // Host disk pressure and inherited query limits must not evict the blocks 
being measured.
+    // Keep a real full disk visible: 100% still enters resource limit mode.
+    suite.setBeConfigTemporary([
+            "enable_evict_file_cache_in_advance": "false",
+            "enable_file_cache_query_limit": "false"
+    ]) {
+        // Nest the thresholds so both application and restoration preserve 
enter >= exit.
+        
suite.setBeConfigTemporary(["file_cache_enter_disk_resource_limit_mode_percent":
 "100"]) {
+            
suite.setBeConfigTemporary(["file_cache_exit_disk_resource_limit_mode_percent": 
"100"]) {
+                suite.awaitUntil(timeoutSeconds, 1) {
+                    def modes = suite.sql """select CACHE_PATH, METRIC_NAME, 
METRIC_VALUE
+                            from information_schema.file_cache_statistics
+                            where METRIC_NAME in ('disk_resource_limit_mode', 
'need_evict_cache_in_advance')
+                            order by CACHE_PATH, METRIC_NAME"""
+                    suite.logger.info("File cache test baseline modes: 
${modes}")
+                    return !modes.isEmpty() && modes.every { 
it[2].toString().toDouble() == 0.0 }
+                }
+                action.call()
+            }
+        }
+    }
+}
+
+logger.info("Added 'withStableFileCache' function to Suite")
diff --git 
a/regression-test/suites/external_table_p0/cache/test_file_cache_features.groovy
 
b/regression-test/suites/external_table_p0/cache/test_file_cache_features.groovy
index 45a0e6b4a4d..92947b3d8ef 100644
--- 
a/regression-test/suites/external_table_p0/cache/test_file_cache_features.groovy
+++ 
b/regression-test/suites/external_table_p0/cache/test_file_cache_features.groovy
@@ -31,122 +31,114 @@ suite("test_file_cache_features", 
"p0,external,nonConcurrent") {
         return;
     }
 
-    sql """set enable_file_cache=true"""
-    sql """set disable_file_cache=false"""
-
-    // Check backend configuration prerequisites
-    // Note: This test case assumes a single backend scenario. Testing with 
single backend is logically equivalent 
-    // to testing with multiple backends having identical configurations, but 
simpler in logic.
-    def enableFileCacheResult = sql """show backend config like 
'enable_file_cache';"""
-    logger.info("enable_file_cache configuration: " + enableFileCacheResult)
-    assertFalse(enableFileCacheResult.size() == 0 || 
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
-            ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
-    
-    def fileCachePathResult = sql """show backend config like 
'file_cache_path';"""
-    logger.info("file_cache_path configuration: " + fileCachePathResult)
-    assertFalse(fileCachePathResult.size() == 0 || fileCachePathResult[0][3] 
== null || fileCachePathResult[0][3].trim().isEmpty(),
-            FILE_CACHE_PATH_CHECK_FAILED_MSG)
-
-    String catalog_name = "test_file_cache_features"
-    String ex_db_name = "`tpch1_parquet`"
-    String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
-    String hms_port = context.config.otherConfigs.get(hivePrefix + "HmsPort")
-
-    def cacheMetricMax = { String metricName ->
-        def r = sql """select max(cast(METRIC_VALUE as double)) from 
information_schema.file_cache_statistics
-                where METRIC_NAME = '${metricName}';"""
-        return (r.size() == 0 || r[0][0] == null) ? null : 
Double.valueOf(r[0][0].toString())
-    }
+    withStableFileCache {
+
+        // Check backend configuration prerequisites
+        // Note: This test case assumes a single backend scenario. Testing 
with single backend is logically equivalent
+        // to testing with multiple backends having identical configurations, 
but simpler in logic.
+        def enableFileCacheResult = sql """show backend config like 
'enable_file_cache';"""
+        logger.info("enable_file_cache configuration: " + 
enableFileCacheResult)
+        assertFalse(enableFileCacheResult.size() == 0 || 
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
+                ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
+
+        def fileCachePathResult = sql """show backend config like 
'file_cache_path';"""
+        logger.info("file_cache_path configuration: " + fileCachePathResult)
+        assertFalse(fileCachePathResult.size() == 0 || 
fileCachePathResult[0][3] == null || fileCachePathResult[0][3].trim().isEmpty(),
+                FILE_CACHE_PATH_CHECK_FAILED_MSG)
+
+        String catalog_name = "test_file_cache_features"
+        String ex_db_name = "`tpch1_parquet`"
+        String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
+        String hms_port = context.config.otherConfigs.get(hivePrefix + 
"HmsPort")
+
+        def cacheMetricMax = { String metricName ->
+            def r = sql """select max(cast(METRIC_VALUE as double)) from 
information_schema.file_cache_statistics
+                    where METRIC_NAME = '${metricName}';"""
+            return (r.size() == 0 || r[0][0] == null) ? null : 
Double.valueOf(r[0][0].toString())
+        }
 
-    sql """drop catalog if exists ${catalog_name} """
-
-    sql """CREATE CATALOG ${catalog_name} PROPERTIES (
-        'type'='hms',
-        'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
-        'hadoop.username' = 'hive'
-    );"""
-
-    sql """switch ${catalog_name}"""
-    sql """select l_returnflag, l_linestatus, 
-        sum(l_quantity) as sum_qty, 
-        sum(l_extendedprice) as sum_base_price, 
-        sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, 
-        sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, 
-        avg(l_quantity) as avg_qty, 
-        avg(l_extendedprice) as avg_price, 
-        avg(l_discount) as avg_disc, 
-        count(*) as count_order 
-    from ${catalog_name}.${ex_db_name}.lineitem 
-    where l_shipdate <= date '1998-12-01' - interval '90' day 
-    group by l_returnflag, l_linestatus 
-    order by l_returnflag, l_linestatus;"""
-    
-    def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend 
config like 'file_cache_background_monitor_interval_ms';"""
-    logger.info("file_cache_background_monitor_interval_ms configuration: " + 
fileCacheBackgroundMonitorIntervalMsResult)
-    assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 || 
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
-            fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(), 
"file_cache_background_monitor_interval_ms is empty or not set to true")
-
-    def totalWaitTime = 
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toInteger() / 1000) as int
-    int pollTimeoutSeconds = Math.max(30, totalWaitTime * 6)
-
-    awaitUntil(pollTimeoutSeconds, 1) {
-        return cacheMetricMax('disk_resource_limit_mode') != null &&
-                cacheMetricMax('need_evict_cache_in_advance') != null &&
-                cacheMetricMax('disk_resource_limit_mode') == 0.0 &&
-                cacheMetricMax('need_evict_cache_in_advance') == 0.0
-    }
+        sql """drop catalog if exists ${catalog_name} """
+
+        sql """CREATE CATALOG ${catalog_name} PROPERTIES (
+            'type'='hms',
+            'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
+            'hadoop.username' = 'hive'
+        );"""
+
+        sql """switch ${catalog_name}"""
+        sql """select l_returnflag, l_linestatus,
+            sum(l_quantity) as sum_qty,
+            sum(l_extendedprice) as sum_base_price,
+            sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
+            sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as 
sum_charge,
+            avg(l_quantity) as avg_qty,
+            avg(l_extendedprice) as avg_price,
+            avg(l_discount) as avg_disc,
+            count(*) as count_order
+        from ${catalog_name}.${ex_db_name}.lineitem
+        where l_shipdate <= date '1998-12-01' - interval '90' day
+        group by l_returnflag, l_linestatus
+        order by l_returnflag, l_linestatus;"""
+
+        def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend 
config like 'file_cache_background_monitor_interval_ms';"""
+        logger.info("file_cache_background_monitor_interval_ms configuration: 
" + fileCacheBackgroundMonitorIntervalMsResult)
+        assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 || 
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
+                
fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(), 
"file_cache_background_monitor_interval_ms is empty or not set to true")
+
+        def totalWaitTime = 
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toInteger() / 1000) as int
+        int pollTimeoutSeconds = Math.max(30, totalWaitTime * 6)
 
-    double initialDiskResourceLimitMode = 
cacheMetricMax('disk_resource_limit_mode')
-    double initialNeedEvictCacheInAdvance = 
cacheMetricMax('need_evict_cache_in_advance')
-    logger.info("Initial file cache features values - 
disk_resource_limit_mode: ${initialDiskResourceLimitMode}, " +
-            "need_evict_cache_in_advance: ${initialNeedEvictCacheInAdvance}")
-    assertTrue(initialDiskResourceLimitMode == 0.0, 
INITIAL_DISK_RESOURCE_LIMIT_MODE_CHECK_FAILED_MSG)
-    assertTrue(initialNeedEvictCacheInAdvance == 0.0, 
INITIAL_NEED_EVICT_CACHE_IN_ADVANCE_CHECK_FAILED_MSG)
-
-    // Set backend configuration parameters for testing
-    setBeConfigTemporary([
-        "file_cache_enter_disk_resource_limit_mode_percent": "2",
-        "file_cache_exit_disk_resource_limit_mode_percent": "1"
-    ]) {
-        // Execute test logic with modified configuration
-        logger.info("Backend configuration set - 
file_cache_enter_disk_resource_limit_mode_percent: 2, " +
-            "file_cache_exit_disk_resource_limit_mode_percent: 1")
+        awaitUntil(pollTimeoutSeconds, 1) {
+            return cacheMetricMax('disk_resource_limit_mode') != null &&
+                    cacheMetricMax('need_evict_cache_in_advance') != null &&
+                    cacheMetricMax('disk_resource_limit_mode') == 0.0 &&
+                    cacheMetricMax('need_evict_cache_in_advance') == 0.0
+        }
+
+        double initialDiskResourceLimitMode = 
cacheMetricMax('disk_resource_limit_mode')
+        double initialNeedEvictCacheInAdvance = 
cacheMetricMax('need_evict_cache_in_advance')
+        logger.info("Initial file cache features values - 
disk_resource_limit_mode: ${initialDiskResourceLimitMode}, " +
+                "need_evict_cache_in_advance: 
${initialNeedEvictCacheInAdvance}")
+        assertTrue(initialDiskResourceLimitMode == 0.0, 
INITIAL_DISK_RESOURCE_LIMIT_MODE_CHECK_FAILED_MSG)
+        assertTrue(initialNeedEvictCacheInAdvance == 0.0, 
INITIAL_NEED_EVICT_CACHE_IN_ADVANCE_CHECK_FAILED_MSG)
+
+        // Zero thresholds enter on any filesystem. Nest updates to keep enter 
>= exit
+        // while applying and restoring settings, even if the monitor runs 
between calls.
+        
setBeConfigTemporary(["file_cache_exit_disk_resource_limit_mode_percent": "0"]) 
{
+            
setBeConfigTemporary(["file_cache_enter_disk_resource_limit_mode_percent": 
"0"]) {
+                awaitUntil(pollTimeoutSeconds, 1) {
+                    return cacheMetricMax('disk_resource_limit_mode') != null 
&&
+                            cacheMetricMax('disk_resource_limit_mode') == 1.0
+                }
+                logger.info("Disk resource limit mode is now active (value = 
${cacheMetricMax('disk_resource_limit_mode')})")
+            }
+        }
 
         awaitUntil(pollTimeoutSeconds, 1) {
             return cacheMetricMax('disk_resource_limit_mode') != null &&
-                    cacheMetricMax('disk_resource_limit_mode') == 1.0
+                    cacheMetricMax('disk_resource_limit_mode') == 0.0
         }
-        logger.info("Disk resource limit mode is now active (value = 
${cacheMetricMax('disk_resource_limit_mode')})")
-    }
 
-    awaitUntil(pollTimeoutSeconds, 1) {
-        return cacheMetricMax('disk_resource_limit_mode') != null &&
-                cacheMetricMax('disk_resource_limit_mode') == 0.0
-    }
-    
-    // Set backend configuration parameters for need_evict_cache_in_advance 
testing
-    setBeConfigTemporary([
-        "enable_evict_file_cache_in_advance": "true",
-        "file_cache_enter_need_evict_cache_in_advance_percent": "2",
-        "file_cache_exit_need_evict_cache_in_advance_percent": "1"
-    ]) {
-        // Execute test logic with modified configuration for 
need_evict_cache_in_advance
-        logger.info("Backend configuration set for need_evict_cache_in_advance 
- " +
-            "enable_evict_file_cache_in_advance: true, " +
-            "file_cache_enter_need_evict_cache_in_advance_percent: 2, " +
-            "file_cache_exit_need_evict_cache_in_advance_percent: 1")
+        // The cache directory consumes an inode, whose used percentage rounds 
up to at
+        // least one. This triggers eviction without assuming a busy test-host 
disk.
+        
setBeConfigTemporary(["file_cache_exit_need_evict_cache_in_advance_percent": 
"0"]) {
+            setBeConfigTemporary([
+                "file_cache_enter_need_evict_cache_in_advance_percent": "1",
+                "enable_evict_file_cache_in_advance": "true"
+            ]) {
+                awaitUntil(pollTimeoutSeconds, 1) {
+                    return cacheMetricMax('need_evict_cache_in_advance') != 
null &&
+                            cacheMetricMax('need_evict_cache_in_advance') == 
1.0
+                }
+                logger.info("Need evict cache in advance mode is now active 
(value = ${cacheMetricMax('need_evict_cache_in_advance')})")
+            }
+        }
 
         awaitUntil(pollTimeoutSeconds, 1) {
             return cacheMetricMax('need_evict_cache_in_advance') != null &&
-                    cacheMetricMax('need_evict_cache_in_advance') == 1.0
+                    cacheMetricMax('need_evict_cache_in_advance') == 0.0
         }
-        logger.info("Need evict cache in advance mode is now active (value = 
${cacheMetricMax('need_evict_cache_in_advance')})")
-    }
 
-    awaitUntil(pollTimeoutSeconds, 1) {
-        return cacheMetricMax('need_evict_cache_in_advance') != null &&
-                cacheMetricMax('need_evict_cache_in_advance') == 0.0
+        return true
     }
-
-    return true
 }
diff --git 
a/regression-test/suites/external_table_p0/cache/test_file_cache_query_limit.groovy
 
b/regression-test/suites/external_table_p0/cache/test_file_cache_query_limit.groovy
index 72fc9950546..fadd9216fb9 100644
--- 
a/regression-test/suites/external_table_p0/cache/test_file_cache_query_limit.groovy
+++ 
b/regression-test/suites/external_table_p0/cache/test_file_cache_query_limit.groovy
@@ -48,14 +48,6 @@ suite("test_file_cache_query_limit", 
"p0,external,nonConcurrent") {
         return
     }
 
-    sql """set enable_file_cache=true"""
-    sql """set disable_file_cache=false"""
-    // The per-query file cache limit is best-effort: once a query reaches it, 
BlockFileCache::try_reserve()
-    // evicts only the query's own blocks that no reader holds, and admits the 
new block anyway when the rest
-    // are still being read. The bound asserted below holds only while few 
blocks are held at once, so the
-    // scans run with one scanner per instance; with up to 16 the limited 
query caches well over its limit.
-    sql """set max_file_scanners_concurrency=1"""
-
     // Note: This test case assumes a single backend scenario. Testing with 
single backend is logically equivalent
     // to testing with multiple backends having identical configurations, but 
simpler in logic.
     // The assumption is load-bearing rather than cosmetic: the HTTP calls 
below clear and inspect one backend's
@@ -72,318 +64,326 @@ suite("test_file_cache_query_limit", 
"p0,external,nonConcurrent") {
     // third-party docker host (hive/es/...), which in a multi-host deployment 
runs no backend at all.
     String beHost = aliveBackends[0].Host
 
-    // Check backend configuration prerequisites
-    def enableFileCacheResult = sql """show backend config like 
'enable_file_cache';"""
-    logger.info("enable_file_cache configuration: " + enableFileCacheResult)
-    assertFalse(enableFileCacheResult.size() == 0 || 
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
-            ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
-
-    def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend 
config like 'file_cache_background_monitor_interval_ms';"""
-    logger.info("file_cache_background_monitor_interval_ms configuration: " + 
fileCacheBackgroundMonitorIntervalMsResult)
-    assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 || 
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
-            fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(), 
FILE_CACHE_BACKGROUND_MONITOR_INTERVAL_CHECK_FAILED_MSG)
-
-    String catalog_name = "test_file_cache_query_limit"
-    String ex_db_name = "tpch1_parquet"
-    String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
-    String hms_port = context.config.otherConfigs.get(hivePrefix + "HmsPort")
-    long queryCacheCapacity
-    long queryLimitBytes
-
-    // Sum a file_cache_statistics metric across all cache paths. 
file_cache_statistics reports
-    // one row per (cache_path, metric_name), so "limit 1" can observe an 
arbitrary path instead
-    // of the whole file cache state.
-    def cacheMetricSum = { String metricName ->
-        def r = sql """select sum(cast(METRIC_VALUE as double)) from 
information_schema.file_cache_statistics
-                where METRIC_NAME = '${metricName}';"""
-        return (r.size() == 0 || r[0][0] == null) ? null : 
Double.valueOf(r[0][0].toString())
-    }
+    withStableFileCache {
+        // The per-query file cache limit is best-effort: once a query reaches 
it, BlockFileCache::try_reserve()
+        // evicts only the query's own blocks that no reader holds, and admits 
the new block anyway when the rest
+        // are still being read. The bound asserted below holds only while few 
blocks are held at once, so the
+        // scans run with one scanner per instance; with up to 16 the limited 
query caches well over its limit.
+        sql """set max_file_scanners_concurrency=1"""
+
+        // Check backend configuration prerequisites
+        def enableFileCacheResult = sql """show backend config like 
'enable_file_cache';"""
+        logger.info("enable_file_cache configuration: " + 
enableFileCacheResult)
+        assertFalse(enableFileCacheResult.size() == 0 || 
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
+                ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
+
+        def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend 
config like 'file_cache_background_monitor_interval_ms';"""
+        logger.info("file_cache_background_monitor_interval_ms configuration: 
" + fileCacheBackgroundMonitorIntervalMsResult)
+        assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 || 
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
+                
fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(), 
FILE_CACHE_BACKGROUND_MONITOR_INTERVAL_CHECK_FAILED_MSG)
+
+        String catalog_name = "test_file_cache_query_limit"
+        String ex_db_name = "tpch1_parquet"
+        String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
+        String hms_port = context.config.otherConfigs.get(hivePrefix + 
"HmsPort")
+        long queryCacheCapacity
+        long queryLimitBytes
+
+        // Sum a file_cache_statistics metric across all cache paths. 
file_cache_statistics reports
+        // one row per (cache_path, metric_name), so "limit 1" can observe an 
arbitrary path instead
+        // of the whole file cache state.
+        def cacheMetricSum = { String metricName ->
+            def r = sql """select sum(cast(METRIC_VALUE as double)) from 
information_schema.file_cache_statistics
+                    where METRIC_NAME = '${metricName}';"""
+            return (r.size() == 0 || r[0][0] == null) ? null : 
Double.valueOf(r[0][0].toString())
+        }
+
+        // Poll a file_cache_statistics metric until predicate holds, or until 
timeout.
+        // file_cache_statistics is refreshed by the background monitor on its 
own cadence,
+        // so waiting a single fixed interval (the previous behavior) races 
the refresh and
+        // makes assertions flaky. On timeout we swallow the exception so the 
caller's
+        // assertFalse below can surface its own metric-specific message.
+        def pollFileCacheMetric = { String metricName, Closure predicate, long 
timeoutSeconds ->
+            try {
+                Awaitility.await()
+                        .atMost(timeoutSeconds, TimeUnit.SECONDS)
+                        .pollInterval(1, TimeUnit.SECONDS)
+                        .until {
+                            Double metricValue = cacheMetricSum(metricName)
+                            return metricValue != null && 
predicate(metricValue)
+                        }
+            } catch (org.awaitility.core.ConditionTimeoutException ignored) {
+                // fall through; the caller's assert will surface the precise 
failure
+            }
+        }
 
-    // Poll a file_cache_statistics metric until predicate holds, or until 
timeout.
-    // file_cache_statistics is refreshed by the background monitor on its own 
cadence,
-    // so waiting a single fixed interval (the previous behavior) races the 
refresh and
-    // makes assertions flaky. On timeout we swallow the exception so the 
caller's
-    // assertFalse below can surface its own metric-specific message.
-    def pollFileCacheMetric = { String metricName, Closure predicate, long 
timeoutSeconds ->
-        try {
+        sql """drop catalog if exists ${catalog_name} """
+
+        sql """CREATE CATALOG ${catalog_name} PROPERTIES (
+            'type'='hms',
+            'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
+            'hadoop.username' = 'hive'
+        );"""
+
+        String query_sql =
+                """select sum(l_quantity) as sum_qty,
+                sum(l_extendedprice) as sum_base_price,
+                sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
+                sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as 
sum_charge,
+                avg(l_quantity) as avg_qty,
+                avg(l_extendedprice) as avg_price,
+                avg(l_discount) as avg_disc,
+                count(*) as count_order
+                from ${catalog_name}.${ex_db_name}.lineitem
+                where l_shipdate <= date '1998-12-01' - interval '90' day
+                group by l_returnflag, l_linestatus
+                order by l_returnflag, l_linestatus;"""
+
+        def webserverPortResult = sql """SHOW BACKEND CONFIG LIKE 
'webserver_port';"""
+        logger.info("webserver_port configuration: " + webserverPortResult)
+        assertFalse(webserverPortResult.size() == 0 || 
webserverPortResult[0][3] == null || webserverPortResult[0][3].trim().isEmpty(),
+                WEB_SERVER_PORT_CHECK_FAILED_MSG)
+
+        String webserver_port = webserverPortResult[0][3]
+
+        def brpcPortResult = sql """SHOW BACKEND CONFIG LIKE 'brpc_port';"""
+        logger.info("brpcPortResult configuration: " + brpcPortResult)
+        assertFalse(brpcPortResult.size() == 0 || brpcPortResult[0][3] == null 
|| brpcPortResult[0][3].trim().isEmpty(),
+                BRPC_PORT_CHECK_FAILED_MSG)
+
+        String brpc_port = brpcPortResult[0][3]
+
+        // Search file cache capacity
+        def command = ["curl", "-X", "POST", "${beHost}:${brpc_port}/vars"]
+        def stringCommand = command.collect{it.toString()}
+        def process = new ProcessBuilder(stringCommand as 
String[]).redirectErrorStream(true).start()
+
+        def output = new StringBuilder()
+        def errorOutput = new StringBuilder()
+        process.inputStream.eachLine{line -> output.append(line).append("\n")}
+        process.errorStream.eachLine{line -> 
errorOutput.append(line).append("\n")}
+
+        // Wait for process completion and check exit status
+        def exitCode = process.waitFor()
+        def fileCacheCapacityResults = output.toString().split("\n")
+                .findAll { it.contains("file_cache_capacity") }
+                .collect { it.split(":")?.last()?.trim() }
+                .findAll { it != null && !it.isEmpty() }
+                .collect { Long.valueOf(it) }
+
+        logger.info("File cache capacities: ${fileCacheCapacityResults}")
+        assertTrue(!fileCacheCapacityResults.isEmpty(), "Failed to find 
file_cache_capacity in brpc metrics")
+        long fileCacheCapacity = fileCacheCapacityResults.sum() as Long
+
+        // Run file cache base test for setting the parameter 
file_cache_query_limit_bytes
+        logger.info("========================= Start running file cache base 
test ========================")
+
+        // Clear file cache
+        command = ["curl", "-X", "POST", 
"${beHost}:${webserver_port}/api/file_cache?op=clear&sync=true"]
+        stringCommand = command.collect{it.toString()}
+        process = new ProcessBuilder(stringCommand as 
String[]).redirectErrorStream(true).start()
+
+        output = new StringBuilder()
+        errorOutput = new StringBuilder()
+        process.inputStream.eachLine{line -> output.append(line).append("\n")}
+        process.errorStream.eachLine{line -> 
errorOutput.append(line).append("\n")}
+
+        // Wait for process completion and check exit status
+        exitCode = process.waitFor()
+        logger.info("File cache clear command output: ${output.toString()}")
+        assertTrue(exitCode == 0, "File cache clear failed with exit code 
${exitCode}. Error: ${errorOutput.toString()}")
+
+        // brpc metrics will be updated at most 5 seconds
+        def totalWaitTime = 
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toLong() / 1000) as int
+        long pollTimeoutSeconds = Math.max(30L, (long) totalWaitTime * 6L)
+
+        def waitBackendConfig = { String configName, String expectedValue ->
             Awaitility.await()
-                    .atMost(timeoutSeconds, TimeUnit.SECONDS)
+                    .atMost(pollTimeoutSeconds, TimeUnit.SECONDS)
                     .pollInterval(1, TimeUnit.SECONDS)
                     .until {
-                        Double metricValue = cacheMetricSum(metricName)
-                        return metricValue != null && predicate(metricValue)
+                        def r = sql """SHOW BACKEND CONFIG LIKE 
'${configName}';"""
+                        return r.size() > 0 && r[0][3] != null && 
r[0][3].toString().equalsIgnoreCase(expectedValue)
                     }
-        } catch (org.awaitility.core.ConditionTimeoutException ignored) {
-            // fall through; the caller's assert will surface the precise 
failure
         }
-    }
 
-    sql """drop catalog if exists ${catalog_name} """
-
-    sql """CREATE CATALOG ${catalog_name} PROPERTIES (
-        'type'='hms',
-        'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
-        'hadoop.username' = 'hive'
-    );"""
-
-    String query_sql =
-            """select sum(l_quantity) as sum_qty,
-            sum(l_extendedprice) as sum_base_price,
-            sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
-            sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as 
sum_charge,
-            avg(l_quantity) as avg_qty,
-            avg(l_extendedprice) as avg_price,
-            avg(l_discount) as avg_disc,
-            count(*) as count_order
-            from ${catalog_name}.${ex_db_name}.lineitem
-            where l_shipdate <= date '1998-12-01' - interval '90' day
-            group by l_returnflag, l_linestatus
-            order by l_returnflag, l_linestatus;"""
-
-    def webserverPortResult = sql """SHOW BACKEND CONFIG LIKE 
'webserver_port';"""
-    logger.info("webserver_port configuration: " + webserverPortResult)
-    assertFalse(webserverPortResult.size() == 0 || webserverPortResult[0][3] 
== null || webserverPortResult[0][3].trim().isEmpty(),
-            WEB_SERVER_PORT_CHECK_FAILED_MSG)
-
-    String webserver_port = webserverPortResult[0][3]
-
-    def brpcPortResult = sql """SHOW BACKEND CONFIG LIKE 'brpc_port';"""
-    logger.info("brpcPortResult configuration: " + brpcPortResult)
-    assertFalse(brpcPortResult.size() == 0 || brpcPortResult[0][3] == null || 
brpcPortResult[0][3].trim().isEmpty(),
-            BRPC_PORT_CHECK_FAILED_MSG)
-
-    String brpc_port = brpcPortResult[0][3]
-
-    // Search file cache capacity
-    def command = ["curl", "-X", "POST", "${beHost}:${brpc_port}/vars"]
-    def stringCommand = command.collect{it.toString()}
-    def process = new ProcessBuilder(stringCommand as 
String[]).redirectErrorStream(true).start()
-
-    def output = new StringBuilder()
-    def errorOutput = new StringBuilder()
-    process.inputStream.eachLine{line -> output.append(line).append("\n")}
-    process.errorStream.eachLine{line -> errorOutput.append(line).append("\n")}
-
-    // Wait for process completion and check exit status
-    def exitCode = process.waitFor()
-    def fileCacheCapacityResults = output.toString().split("\n")
-            .findAll { it.contains("file_cache_capacity") }
-            .collect { it.split(":")?.last()?.trim() }
-            .findAll { it != null && !it.isEmpty() }
-            .collect { Long.valueOf(it) }
-
-    logger.info("File cache capacities: ${fileCacheCapacityResults}")
-    assertTrue(!fileCacheCapacityResults.isEmpty(), "Failed to find 
file_cache_capacity in brpc metrics")
-    long fileCacheCapacity = fileCacheCapacityResults.sum() as Long
-
-    // Run file cache base test for setting the parameter 
file_cache_query_limit_bytes
-    logger.info("========================= Start running file cache base test 
========================")
-
-    // Clear file cache
-    command = ["curl", "-X", "POST", 
"${beHost}:${webserver_port}/api/file_cache?op=clear&sync=true"]
-    stringCommand = command.collect{it.toString()}
-    process = new ProcessBuilder(stringCommand as 
String[]).redirectErrorStream(true).start()
-
-    output = new StringBuilder()
-    errorOutput = new StringBuilder()
-    process.inputStream.eachLine{line -> output.append(line).append("\n")}
-    process.errorStream.eachLine{line -> errorOutput.append(line).append("\n")}
-
-    // Wait for process completion and check exit status
-    exitCode = process.waitFor()
-    logger.info("File cache clear command output: ${output.toString()}")
-    assertTrue(exitCode == 0, "File cache clear failed with exit code 
${exitCode}. Error: ${errorOutput.toString()}")
-
-    // brpc metrics will be updated at most 5 seconds
-    def totalWaitTime = 
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toLong() / 1000) as int
-    long pollTimeoutSeconds = Math.max(30L, (long) totalWaitTime * 6L)
-
-    def waitBackendConfig = { String configName, String expectedValue ->
-        Awaitility.await()
-                .atMost(pollTimeoutSeconds, TimeUnit.SECONDS)
-                .pollInterval(1, TimeUnit.SECONDS)
-                .until {
-                    def r = sql """SHOW BACKEND CONFIG LIKE '${configName}';"""
-                    return r.size() > 0 && r[0][3] != null && 
r[0][3].toString().equalsIgnoreCase(expectedValue)
-                }
-    }
+        // Poll until the cache clear has drained the LRU queue. The HTTP 
clear endpoint with sync=true
+        // deletes blocks synchronously, but the queue counters are 
republished by the background monitor
+        // thread on its own cadence — so a single fixed-time wait can race 
the refresh.
+        pollFileCacheMetric('normal_queue_curr_size', { it == 0.0 }, 
pollTimeoutSeconds)
+        pollFileCacheMetric('normal_queue_curr_elements', { it == 0.0 }, 
pollTimeoutSeconds)
 
-    // Poll until the cache clear has drained the LRU queue. The HTTP clear 
endpoint with sync=true
-    // deletes blocks synchronously, but the queue counters are republished by 
the background monitor
-    // thread on its own cadence — so a single fixed-time wait can race the 
refresh.
-    pollFileCacheMetric('normal_queue_curr_size', { it == 0.0 }, 
pollTimeoutSeconds)
-    pollFileCacheMetric('normal_queue_curr_elements', { it == 0.0 }, 
pollTimeoutSeconds)
-
-    Double initialNormalQueueCurrSize = 
cacheMetricSum('normal_queue_curr_size')
-    logger.info("normal_queue_curr_size sum result: " + 
initialNormalQueueCurrSize)
-    assertFalse(initialNormalQueueCurrSize == null || 
initialNormalQueueCurrSize != 0.0,
-            INITIAL_NORMAL_QUEUE_CURR_SIZE_NOT_ZERO_MSG)
-
-    Double initialNormalQueueCurrElements = 
cacheMetricSum('normal_queue_curr_elements')
-    logger.info("normal_queue_curr_elements sum result: " + 
initialNormalQueueCurrElements)
-    assertFalse(initialNormalQueueCurrElements == null || 
initialNormalQueueCurrElements != 0.0,
-            INITIAL_NORMAL_QUEUE_CURR_ELEMENTS_NOT_ZERO_MSG)
-
-    logger.info("Initial normal queue curr size and elements - size: 
${initialNormalQueueCurrSize} , " +
-            "elements: ${initialNormalQueueCurrElements}")
-
-    setBeConfigTemporary([
-            "enable_file_cache_query_limit": "false"
-    ]) {
-        // Execute test logic with modified configuration for 
file_cache_query_limit
-        logger.info("Backend configuration set - 
enable_file_cache_query_limit: false")
-
-        waitBackendConfig("enable_file_cache_query_limit", "false")
-
-        // Check if the configuration is modified
-        def enableFileCacheQueryLimitResult = sql """SHOW BACKEND CONFIG LIKE 
'enable_file_cache_query_limit';"""
-        logger.info("enable_file_cache_query_limit configuration: " + 
enableFileCacheQueryLimitResult)
-        assertFalse(enableFileCacheQueryLimitResult.size() == 0 || 
enableFileCacheQueryLimitResult[0][3] == null || 
enableFileCacheQueryLimitResult[0][3] != "false",
-                ENABLE_FILE_CACHE_QUERY_LIMIT_CHECK_FALSE_FAILED_MSG)
-
-        sql """switch ${catalog_name}"""
-        // load the table into file cache
-        sql query_sql
-
-        // Poll until the query has populated the cache.
-        pollFileCacheMetric('normal_queue_curr_elements', { it > 0.0 }, 
pollTimeoutSeconds)
-        pollFileCacheMetric('normal_queue_curr_size', { it > 0.0 }, 
pollTimeoutSeconds)
-
-        Double baseNormalQueueCurrElements = 
cacheMetricSum('normal_queue_curr_elements')
-        logger.info("normal_queue_curr_elements sum result: " + 
baseNormalQueueCurrElements)
-        assertFalse(baseNormalQueueCurrElements == null || 
baseNormalQueueCurrElements == 0.0,
-                BASE_NORMAL_QUEUE_CURR_ELEMENTS_IS_ZERO_MSG)
-
-        Double baseNormalQueueCurrSize = 
cacheMetricSum('normal_queue_curr_size')
-        logger.info("normal_queue_curr_size sum result: " + 
baseNormalQueueCurrSize)
-        assertFalse(baseNormalQueueCurrSize == null || baseNormalQueueCurrSize 
== 0.0,
-                BASE_NORMAL_QUEUE_CURR_SIZE_IS_ZERO_MSG)
-
-        queryCacheCapacity = baseNormalQueueCurrSize as Long
-    }
+        Double initialNormalQueueCurrSize = 
cacheMetricSum('normal_queue_curr_size')
+        logger.info("normal_queue_curr_size sum result: " + 
initialNormalQueueCurrSize)
+        assertFalse(initialNormalQueueCurrSize == null || 
initialNormalQueueCurrSize != 0.0,
+                INITIAL_NORMAL_QUEUE_CURR_SIZE_NOT_ZERO_MSG)
 
-    // The parameter file_cache_query_limit_percent must be set smaller than 
the cache capacity required by the query
-    def fileCacheQueryLimitPercent = (queryCacheCapacity / fileCacheCapacity) 
* 100
-    logger.info("file_cache_query_limit_percent: " + 
fileCacheQueryLimitPercent)
-
-    logger.info("========================== End running file cache base test 
=========================")
-
-    logger.info("==================== Start running file cache query limit 
test 1 ====================")
-
-    long fileCacheQueryLimitPercentTest1 = Math.max(1L, 
(fileCacheQueryLimitPercent / 2) as Long)
-    queryLimitBytes = (fileCacheCapacity * fileCacheQueryLimitPercentTest1 / 
100) as Long
-    logger.info("file_cache_query_limit_percent_test1: " + 
fileCacheQueryLimitPercentTest1)
-    logger.info("query_limit_bytes: ${queryLimitBytes}, query_cache_capacity: 
${queryCacheCapacity}")
-    assertTrue(queryLimitBytes > 0 && queryLimitBytes < queryCacheCapacity,
-            FILE_CACHE_QUERY_LIMIT_BYTES_CHECK_FAILED_MSG)
-
-    // Clear file cache
-    process = new ProcessBuilder(stringCommand as 
String[]).redirectErrorStream(true).start()
-
-    output = new StringBuilder()
-    errorOutput = new StringBuilder()
-    process.inputStream.eachLine{line -> output.append(line).append("\n")}
-    process.errorStream.eachLine{line -> errorOutput.append(line).append("\n")}
-
-    // Wait for process completion and check exit status
-    exitCode = process.waitFor()
-    logger.info("File cache clear command output: ${output.toString()}")
-    assertTrue(exitCode == 0, "File cache clear failed with exit code 
${exitCode}. Error: ${errorOutput.toString()}")
-
-    // Poll until the file cache is fully cleared again.
-    pollFileCacheMetric('normal_queue_curr_size', { it == 0.0 }, 
pollTimeoutSeconds)
-    pollFileCacheMetric('normal_queue_curr_elements', { it == 0.0 }, 
pollTimeoutSeconds)
-
-    // ===== Normal Queue Metrics Check =====
-    // Check normal queue current size
-    initialNormalQueueCurrSize = cacheMetricSum('normal_queue_curr_size')
-    logger.info("normal_queue_curr_size sum result: " + 
initialNormalQueueCurrSize)
-    assertFalse(initialNormalQueueCurrSize == null || 
initialNormalQueueCurrSize != 0.0,
-            INITIAL_NORMAL_QUEUE_CURR_SIZE_NOT_ZERO_MSG)
-
-    // Check normal queue current elements
-    initialNormalQueueCurrElements = 
cacheMetricSum('normal_queue_curr_elements')
-    logger.info("normal_queue_curr_elements sum result: " + 
initialNormalQueueCurrElements)
-    assertFalse(initialNormalQueueCurrElements == null || 
initialNormalQueueCurrElements != 0.0,
-            INITIAL_NORMAL_QUEUE_CURR_ELEMENTS_NOT_ZERO_MSG)
-
-    // Check normal queue max size
-    Double initialNormalQueueMaxSize = cacheMetricSum('normal_queue_max_size')
-    logger.info("normal_queue_max_size sum result: " + 
initialNormalQueueMaxSize)
-    assertFalse(initialNormalQueueMaxSize == null || initialNormalQueueMaxSize 
== 0.0,
-            INITIAL_NORMAL_QUEUE_MAX_SIZE_IS_ZERO_MSG)
-
-    // Check normal queue max elements
-    Double initialNormalQueueMaxElements = 
cacheMetricSum('normal_queue_max_elements')
-    logger.info("normal_queue_max_elements sum result: " + 
initialNormalQueueMaxElements)
-    assertFalse(initialNormalQueueMaxElements == null || 
initialNormalQueueMaxElements == 0.0,
-            INITIAL_NORMAL_QUEUE_MAX_ELEMENTS_IS_ZERO_MSG)
-
-    logger.info("Initial normal queue curr size and elements - size: 
${initialNormalQueueCurrSize} , " +
+        Double initialNormalQueueCurrElements = 
cacheMetricSum('normal_queue_curr_elements')
+        logger.info("normal_queue_curr_elements sum result: " + 
initialNormalQueueCurrElements)
+        assertFalse(initialNormalQueueCurrElements == null || 
initialNormalQueueCurrElements != 0.0,
+                INITIAL_NORMAL_QUEUE_CURR_ELEMENTS_NOT_ZERO_MSG)
+
+        logger.info("Initial normal queue curr size and elements - size: 
${initialNormalQueueCurrSize} , " +
                 "elements: ${initialNormalQueueCurrElements}")
 
-    logger.info("Initial normal queue max size and elements - size: 
${initialNormalQueueMaxSize} , " +
-                "elements: ${initialNormalQueueMaxElements}")
+        setBeConfigTemporary([
+                "enable_file_cache_query_limit": "false"
+        ]) {
+            // Execute test logic with modified configuration for 
file_cache_query_limit
+            logger.info("Backend configuration set - 
enable_file_cache_query_limit: false")
+
+            waitBackendConfig("enable_file_cache_query_limit", "false")
 
-    // ===== Hit And Read Counts Metrics Check =====
-    // total_hit_counts / total_read_counts are also reported per cache path.
-    Double initialTotalHitCounts = cacheMetricSum('total_hit_counts')
-    Double initialTotalReadCounts = cacheMetricSum('total_read_counts')
-    logger.info("Initial total_hit_counts (sum): ${initialTotalHitCounts}, 
total_read_counts (sum): ${initialTotalReadCounts}")
+            // Check if the configuration is modified
+            def enableFileCacheQueryLimitResult = sql """SHOW BACKEND CONFIG 
LIKE 'enable_file_cache_query_limit';"""
+            logger.info("enable_file_cache_query_limit configuration: " + 
enableFileCacheQueryLimitResult)
+            assertFalse(enableFileCacheQueryLimitResult.size() == 0 || 
enableFileCacheQueryLimitResult[0][3] == null || 
enableFileCacheQueryLimitResult[0][3] != "false",
+                    ENABLE_FILE_CACHE_QUERY_LIMIT_CHECK_FALSE_FAILED_MSG)
 
-    // Set backend configuration parameters for file_cache_query_limit test 1
-    setBeConfigTemporary([
-            "enable_file_cache_query_limit": "true"
-    ]) {
-        // Execute test logic with modified configuration for 
file_cache_query_limit
-        logger.info("Backend configuration set - 
enable_file_cache_query_limit: true")
+            sql """switch ${catalog_name}"""
+            // load the table into file cache
+            sql query_sql
 
-        sql """set file_cache_query_limit_percent =  
${fileCacheQueryLimitPercentTest1}"""
+            // Poll until the query has populated the cache.
+            pollFileCacheMetric('normal_queue_curr_elements', { it > 0.0 }, 
pollTimeoutSeconds)
+            pollFileCacheMetric('normal_queue_curr_size', { it > 0.0 }, 
pollTimeoutSeconds)
 
-        waitBackendConfig("enable_file_cache_query_limit", "true")
+            Double baseNormalQueueCurrElements = 
cacheMetricSum('normal_queue_curr_elements')
+            logger.info("normal_queue_curr_elements sum result: " + 
baseNormalQueueCurrElements)
+            assertFalse(baseNormalQueueCurrElements == null || 
baseNormalQueueCurrElements == 0.0,
+                    BASE_NORMAL_QUEUE_CURR_ELEMENTS_IS_ZERO_MSG)
 
-        // Check if the configuration is modified
-        def enableFileCacheQueryLimitResult = sql """SHOW BACKEND CONFIG LIKE 
'enable_file_cache_query_limit';"""
-        logger.info("enable_file_cache_query_limit configuration: " + 
enableFileCacheQueryLimitResult)
-        assertFalse(enableFileCacheQueryLimitResult.size() == 0 || 
enableFileCacheQueryLimitResult[0][3] == null || 
enableFileCacheQueryLimitResult[0][3] != "true",
-                ENABLE_FILE_CACHE_QUERY_LIMIT_CHECK_TRUE_FAILED_MSG)
+            Double baseNormalQueueCurrSize = 
cacheMetricSum('normal_queue_curr_size')
+            logger.info("normal_queue_curr_size sum result: " + 
baseNormalQueueCurrSize)
+            assertFalse(baseNormalQueueCurrSize == null || 
baseNormalQueueCurrSize == 0.0,
+                    BASE_NORMAL_QUEUE_CURR_SIZE_IS_ZERO_MSG)
 
-        sql """switch ${catalog_name}"""
+            queryCacheCapacity = baseNormalQueueCurrSize as Long
+        }
 
-        // load the table into file cache
-        sql query_sql
+        // The parameter file_cache_query_limit_percent must be set smaller 
than the cache capacity required by the query
+        def fileCacheQueryLimitPercent = (queryCacheCapacity / 
fileCacheCapacity) * 100
+        logger.info("file_cache_query_limit_percent: " + 
fileCacheQueryLimitPercent)
+
+        logger.info("========================== End running file cache base 
test =========================")
 
-        // Poll until the query has populated the cache under the new 
file_cache_query_limit.
-        pollFileCacheMetric('normal_queue_curr_size', { it > 0.0 }, 
pollTimeoutSeconds)
-        pollFileCacheMetric('normal_queue_curr_elements', { it > 0.0 }, 
pollTimeoutSeconds)
+        logger.info("==================== Start running file cache query limit 
test 1 ====================")
+
+        long fileCacheQueryLimitPercentTest1 = Math.max(1L, 
(fileCacheQueryLimitPercent / 2) as Long)
+        queryLimitBytes = (fileCacheCapacity * fileCacheQueryLimitPercentTest1 
/ 100) as Long
+        logger.info("file_cache_query_limit_percent_test1: " + 
fileCacheQueryLimitPercentTest1)
+        logger.info("query_limit_bytes: ${queryLimitBytes}, 
query_cache_capacity: ${queryCacheCapacity}")
+        assertTrue(queryLimitBytes > 0 && queryLimitBytes < queryCacheCapacity,
+                FILE_CACHE_QUERY_LIMIT_BYTES_CHECK_FAILED_MSG)
 
-        // Get updated value of normal queue current elements and max elements 
after cache operations
-        // Check if updated values are greater than initial values
-        Double updatedNormalQueueCurrSize = 
cacheMetricSum('normal_queue_curr_size')
-        Double updatedNormalQueueCurrElements = 
cacheMetricSum('normal_queue_curr_elements')
+        // Clear file cache
+        process = new ProcessBuilder(stringCommand as 
String[]).redirectErrorStream(true).start()
 
-        logger.info("Updated normal queue curr size and elements sum - size: 
${updatedNormalQueueCurrSize} , " +
-                "elements: ${updatedNormalQueueCurrElements}")
+        output = new StringBuilder()
+        errorOutput = new StringBuilder()
+        process.inputStream.eachLine{line -> output.append(line).append("\n")}
+        process.errorStream.eachLine{line -> 
errorOutput.append(line).append("\n")}
 
-        assertTrue(updatedNormalQueueCurrSize > 0.0, 
NORMAL_QUEUE_CURR_SIZE_NOT_GREATER_THAN_ZERO_MSG)
-        assertTrue(updatedNormalQueueCurrElements > 0.0, 
NORMAL_QUEUE_CURR_ELEMENTS_NOT_GREATER_THAN_ZERO_MSG)
+        // Wait for process completion and check exit status
+        exitCode = process.waitFor()
+        logger.info("File cache clear command output: ${output.toString()}")
+        assertTrue(exitCode == 0, "File cache clear failed with exit code 
${exitCode}. Error: ${errorOutput.toString()}")
 
-        logger.info("Normal queue curr size and query cache limit comparison - 
normal queue curr size: ${updatedNormalQueueCurrSize as Long} , " +
-                "query cache limit: ${queryLimitBytes}, baseline query cache 
capacity: ${queryCacheCapacity}")
+        // Poll until the file cache is fully cleared again.
+        pollFileCacheMetric('normal_queue_curr_size', { it == 0.0 }, 
pollTimeoutSeconds)
+        pollFileCacheMetric('normal_queue_curr_elements', { it == 0.0 }, 
pollTimeoutSeconds)
 
-        assertTrue((updatedNormalQueueCurrSize as Long) <= queryLimitBytes,
-                NORMAL_QUEUE_CURR_SIZE_GREATER_THAN_QUERY_CACHE_LIMIT_MSG)
+        // ===== Normal Queue Metrics Check =====
+        // Check normal queue current size
+        initialNormalQueueCurrSize = cacheMetricSum('normal_queue_curr_size')
+        logger.info("normal_queue_curr_size sum result: " + 
initialNormalQueueCurrSize)
+        assertFalse(initialNormalQueueCurrSize == null || 
initialNormalQueueCurrSize != 0.0,
+                INITIAL_NORMAL_QUEUE_CURR_SIZE_NOT_ZERO_MSG)
 
-        Double updatedTotalHitCounts = cacheMetricSum('total_hit_counts')
-        Double updatedTotalReadCounts = cacheMetricSum('total_read_counts')
+        // Check normal queue current elements
+        initialNormalQueueCurrElements = 
cacheMetricSum('normal_queue_curr_elements')
+        logger.info("normal_queue_curr_elements sum result: " + 
initialNormalQueueCurrElements)
+        assertFalse(initialNormalQueueCurrElements == null || 
initialNormalQueueCurrElements != 0.0,
+                INITIAL_NORMAL_QUEUE_CURR_ELEMENTS_NOT_ZERO_MSG)
 
-        logger.info("Total hit and read counts comparison - hit counts: 
${initialTotalHitCounts} -> " +
-                "${updatedTotalHitCounts} , read counts: 
${initialTotalReadCounts} -> ${updatedTotalReadCounts}")
+        // Check normal queue max size
+        Double initialNormalQueueMaxSize = 
cacheMetricSum('normal_queue_max_size')
+        logger.info("normal_queue_max_size sum result: " + 
initialNormalQueueMaxSize)
+        assertFalse(initialNormalQueueMaxSize == null || 
initialNormalQueueMaxSize == 0.0,
+                INITIAL_NORMAL_QUEUE_MAX_SIZE_IS_ZERO_MSG)
 
-        assertTrue(updatedTotalReadCounts > initialTotalReadCounts, 
TOTAL_READ_COUNTS_DID_NOT_INCREASE_MSG)
-    }
+        // Check normal queue max elements
+        Double initialNormalQueueMaxElements = 
cacheMetricSum('normal_queue_max_elements')
+        logger.info("normal_queue_max_elements sum result: " + 
initialNormalQueueMaxElements)
+        assertFalse(initialNormalQueueMaxElements == null || 
initialNormalQueueMaxElements == 0.0,
+                INITIAL_NORMAL_QUEUE_MAX_ELEMENTS_IS_ZERO_MSG)
+
+        logger.info("Initial normal queue curr size and elements - size: 
${initialNormalQueueCurrSize} , " +
+                    "elements: ${initialNormalQueueCurrElements}")
+
+        logger.info("Initial normal queue max size and elements - size: 
${initialNormalQueueMaxSize} , " +
+                    "elements: ${initialNormalQueueMaxElements}")
+
+        // ===== Hit And Read Counts Metrics Check =====
+        // total_hit_counts / total_read_counts are also reported per cache 
path.
+        Double initialTotalHitCounts = cacheMetricSum('total_hit_counts')
+        Double initialTotalReadCounts = cacheMetricSum('total_read_counts')
+        logger.info("Initial total_hit_counts (sum): ${initialTotalHitCounts}, 
total_read_counts (sum): ${initialTotalReadCounts}")
 
-    logger.info("===================== End running file cache query limit test 
1 =====================")
+        // Set backend configuration parameters for file_cache_query_limit 
test 1
+        setBeConfigTemporary([
+                "enable_file_cache_query_limit": "true"
+        ]) {
+            // Execute test logic with modified configuration for 
file_cache_query_limit
+            logger.info("Backend configuration set - 
enable_file_cache_query_limit: true")
 
-    return true;
+            sql """set file_cache_query_limit_percent =  
${fileCacheQueryLimitPercentTest1}"""
+
+            waitBackendConfig("enable_file_cache_query_limit", "true")
+
+            // Check if the configuration is modified
+            def enableFileCacheQueryLimitResult = sql """SHOW BACKEND CONFIG 
LIKE 'enable_file_cache_query_limit';"""
+            logger.info("enable_file_cache_query_limit configuration: " + 
enableFileCacheQueryLimitResult)
+            assertFalse(enableFileCacheQueryLimitResult.size() == 0 || 
enableFileCacheQueryLimitResult[0][3] == null || 
enableFileCacheQueryLimitResult[0][3] != "true",
+                    ENABLE_FILE_CACHE_QUERY_LIMIT_CHECK_TRUE_FAILED_MSG)
+
+            sql """switch ${catalog_name}"""
+
+            // load the table into file cache
+            sql query_sql
+
+            // Poll until the query has populated the cache under the new 
file_cache_query_limit.
+            pollFileCacheMetric('normal_queue_curr_size', { it > 0.0 }, 
pollTimeoutSeconds)
+            pollFileCacheMetric('normal_queue_curr_elements', { it > 0.0 }, 
pollTimeoutSeconds)
+
+            // Get updated value of normal queue current elements and max 
elements after cache operations
+            // Check if updated values are greater than initial values
+            Double updatedNormalQueueCurrSize = 
cacheMetricSum('normal_queue_curr_size')
+            Double updatedNormalQueueCurrElements = 
cacheMetricSum('normal_queue_curr_elements')
+
+            logger.info("Updated normal queue curr size and elements sum - 
size: ${updatedNormalQueueCurrSize} , " +
+                    "elements: ${updatedNormalQueueCurrElements}")
+
+            assertTrue(updatedNormalQueueCurrSize > 0.0, 
NORMAL_QUEUE_CURR_SIZE_NOT_GREATER_THAN_ZERO_MSG)
+            assertTrue(updatedNormalQueueCurrElements > 0.0, 
NORMAL_QUEUE_CURR_ELEMENTS_NOT_GREATER_THAN_ZERO_MSG)
+
+            logger.info("Normal queue curr size and query cache limit 
comparison - normal queue curr size: ${updatedNormalQueueCurrSize as Long} , " +
+                    "query cache limit: ${queryLimitBytes}, baseline query 
cache capacity: ${queryCacheCapacity}")
+
+            assertTrue((updatedNormalQueueCurrSize as Long) <= queryLimitBytes,
+                    NORMAL_QUEUE_CURR_SIZE_GREATER_THAN_QUERY_CACHE_LIMIT_MSG)
+
+            Double updatedTotalHitCounts = cacheMetricSum('total_hit_counts')
+            Double updatedTotalReadCounts = cacheMetricSum('total_read_counts')
+
+            logger.info("Total hit and read counts comparison - hit counts: 
${initialTotalHitCounts} -> " +
+                    "${updatedTotalHitCounts} , read counts: 
${initialTotalReadCounts} -> ${updatedTotalReadCounts}")
+
+            assertTrue(updatedTotalReadCounts > initialTotalReadCounts, 
TOTAL_READ_COUNTS_DID_NOT_INCREASE_MSG)
+        }
+
+        logger.info("===================== End running file cache query limit 
test 1 =====================")
+
+        return true;
+    }
 }
diff --git 
a/regression-test/suites/external_table_p0/cache/test_file_cache_statistics.groovy
 
b/regression-test/suites/external_table_p0/cache/test_file_cache_statistics.groovy
index 4c4468dadda..64413bb11a4 100644
--- 
a/regression-test/suites/external_table_p0/cache/test_file_cache_statistics.groovy
+++ 
b/regression-test/suites/external_table_p0/cache/test_file_cache_statistics.groovy
@@ -43,129 +43,125 @@ suite("test_file_cache_statistics", 
"p0,external,nonConcurrent") {
         return;
     }
 
-    sql """set enable_file_cache=true"""
-    sql """set disable_file_cache=false"""
-    // This case validates BlockFileCache counters. Keep upper-layer caches 
and scan scheduling
-    // from serving or cancelling the repeated read before it reaches 
BlockFileCache.
-    sql """set enable_sql_cache=false"""
-    sql """set enable_hive_sql_cache=false"""
-    sql """set enable_parquet_file_page_cache=false"""
-    sql """set parallel_pipeline_task_num=1"""
-
-    // Check backend configuration prerequisites
-    // Note: This test case assumes a single backend scenario. Testing with 
single backend is logically equivalent 
-    // to testing with multiple backends having identical configurations, but 
simpler in logic.
-    def enableFileCacheResult = sql """show backend config like 
'enable_file_cache';"""
-    logger.info("enable_file_cache configuration: " + enableFileCacheResult)
-    assertFalse(enableFileCacheResult.size() == 0 || 
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
-            ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
-    
-    def fileCachePathResult = sql """show backend config like 
'file_cache_path';"""
-    logger.info("file_cache_path configuration: " + fileCachePathResult)
-    assertFalse(fileCachePathResult.size() == 0 || fileCachePathResult[0][3] 
== null || fileCachePathResult[0][3].trim().isEmpty(),
-            FILE_CACHE_PATH_CHECK_FAILED_MSG)
-
-    String catalog_name = "test_file_cache_statistics"
-    String ex_db_name = "`default`"
-    String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
-    String hms_port = context.config.otherConfigs.get(hivePrefix + "HmsPort")
-
-    def cacheMetric = { String metricName, String aggregateFunc ->
-        def r = sql """select ${aggregateFunc}(cast(METRIC_VALUE as double)) 
from information_schema.file_cache_statistics
-                where METRIC_NAME = '${metricName}';"""
-        return (r.size() == 0 || r[0][0] == null) ? null : 
Double.valueOf(r[0][0].toString())
-    }
-    def cacheMetricSum = { String metricName -> cacheMetric(metricName, "sum") 
}
-    def cacheMetricMax = { String metricName -> cacheMetric(metricName, "max") 
}
-
-    sql """drop catalog if exists ${catalog_name} """
-
-    sql """CREATE CATALOG ${catalog_name} PROPERTIES (
-        'type'='hms',
-        'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
-        'hadoop.username' = 'hive'
-    );"""
-
-    sql """switch ${catalog_name}"""
-
-    // Pin the query to one partition file instead of racing all six file scan 
ranges under LIMIT 1.
-    String querySql = """select * from 
${catalog_name}.${ex_db_name}.parquet_partition_table
-            where nation='cn' and city='beijing'
-            and l_orderkey=1 and l_partkey=1534 limit 1;"""
-
-    // load the table into file cache
-    sql querySql
-    // do it twice to make sure the table block could hit the cache
-    order_qt_1 querySql
-
-    def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend 
config like 'file_cache_background_monitor_interval_ms';"""
-    logger.info("file_cache_background_monitor_interval_ms configuration: " + 
fileCacheBackgroundMonitorIntervalMsResult)
-    assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 || 
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
-            fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(), 
"file_cache_background_monitor_interval_ms is empty or not set to true")
-
-    def totalWaitTime = 
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toInteger() / 1000) as int
-    int pollTimeoutSeconds = Math.max(30, totalWaitTime * 6)
-
-    awaitUntil(pollTimeoutSeconds, 1) {
-        return cacheMetricMax('hits_ratio') != null && 
cacheMetricMax('hits_ratio') > 0.0 &&
-                cacheMetricMax('hits_ratio_1h') != null && 
cacheMetricMax('hits_ratio_1h') > 0.0 &&
-                cacheMetricMax('hits_ratio_5m') != null && 
cacheMetricMax('hits_ratio_5m') > 0.0 &&
-                cacheMetricSum('normal_queue_curr_size') != null && 
cacheMetricSum('normal_queue_curr_size') > 0.0 &&
-                cacheMetricSum('normal_queue_max_size') != null && 
cacheMetricSum('normal_queue_max_size') > 0.0 &&
-                cacheMetricSum('normal_queue_curr_elements') != null && 
cacheMetricSum('normal_queue_curr_elements') > 0.0 &&
-                cacheMetricSum('normal_queue_max_elements') != null && 
cacheMetricSum('normal_queue_max_elements') > 0.0 &&
-                cacheMetricSum('total_hit_counts') != null && 
cacheMetricSum('total_hit_counts') > 0.0 &&
-                cacheMetricSum('total_read_counts') != null && 
cacheMetricSum('total_read_counts') > 0.0
-    }
+    withStableFileCache {
+        // Keep LIMIT cancellation from racing the single partition file being 
measured.
+        sql """set parallel_pipeline_task_num=1"""
+
+        // Check backend configuration prerequisites
+        // Note: This test case assumes a single backend scenario. Testing 
with single backend is logically equivalent
+        // to testing with multiple backends having identical configurations, 
but simpler in logic.
+        def enableFileCacheResult = sql """show backend config like 
'enable_file_cache';"""
+        logger.info("enable_file_cache configuration: " + 
enableFileCacheResult)
+        assertFalse(enableFileCacheResult.size() == 0 || 
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
+                ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
+
+        def fileCachePathResult = sql """show backend config like 
'file_cache_path';"""
+        logger.info("file_cache_path configuration: " + fileCachePathResult)
+        assertFalse(fileCachePathResult.size() == 0 || 
fileCachePathResult[0][3] == null || fileCachePathResult[0][3].trim().isEmpty(),
+                FILE_CACHE_PATH_CHECK_FAILED_MSG)
+
+        String catalog_name = "test_file_cache_statistics"
+        String ex_db_name = "`default`"
+        String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
+        String hms_port = context.config.otherConfigs.get(hivePrefix + 
"HmsPort")
+
+        def cacheMetric = { String metricName, String aggregateFunc ->
+            def r = sql """select ${aggregateFunc}(cast(METRIC_VALUE as 
double)) from information_schema.file_cache_statistics
+                    where METRIC_NAME = '${metricName}';"""
+            return (r.size() == 0 || r[0][0] == null) ? null : 
Double.valueOf(r[0][0].toString())
+        }
+        def cacheMetricSum = { String metricName -> cacheMetric(metricName, 
"sum") }
+        def cacheMetricMax = { String metricName -> cacheMetric(metricName, 
"max") }
+
+        sql """drop catalog if exists ${catalog_name} """
+
+        sql """CREATE CATALOG ${catalog_name} PROPERTIES (
+            'type'='hms',
+            'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
+            'hadoop.username' = 'hive'
+        );"""
+
+        sql """switch ${catalog_name}"""
+
+        // Pin the query to one partition file instead of racing all six file 
scan ranges under LIMIT 1.
+        String querySql = """select * from 
${catalog_name}.${ex_db_name}.parquet_partition_table
+                where nation='cn' and city='beijing'
+                and l_orderkey=1 and l_partkey=1534 limit 1;"""
+
+        // load the table into file cache
+        sql querySql
+        // do it twice to make sure the table block could hit the cache
+        order_qt_1 querySql
+
+        def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend 
config like 'file_cache_background_monitor_interval_ms';"""
+        logger.info("file_cache_background_monitor_interval_ms configuration: 
" + fileCacheBackgroundMonitorIntervalMsResult)
+        assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 || 
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
+                
fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(), 
"file_cache_background_monitor_interval_ms is empty or not set to true")
+
+        def totalWaitTime = 
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toInteger() / 1000) as int
+        int pollTimeoutSeconds = Math.max(30, totalWaitTime * 6)
+
+        awaitUntil(pollTimeoutSeconds, 1) {
+            return cacheMetricMax('hits_ratio') != null && 
cacheMetricMax('hits_ratio') > 0.0 &&
+                    cacheMetricMax('hits_ratio_1h') != null && 
cacheMetricMax('hits_ratio_1h') > 0.0 &&
+                    cacheMetricMax('hits_ratio_5m') != null && 
cacheMetricMax('hits_ratio_5m') > 0.0 &&
+                    cacheMetricSum('normal_queue_curr_size') != null && 
cacheMetricSum('normal_queue_curr_size') > 0.0 &&
+                    cacheMetricSum('normal_queue_max_size') != null && 
cacheMetricSum('normal_queue_max_size') > 0.0 &&
+                    cacheMetricSum('normal_queue_curr_elements') != null && 
cacheMetricSum('normal_queue_curr_elements') > 0.0 &&
+                    cacheMetricSum('normal_queue_max_elements') != null && 
cacheMetricSum('normal_queue_max_elements') > 0.0 &&
+                    cacheMetricSum('total_hit_counts') != null && 
cacheMetricSum('total_hit_counts') > 0.0 &&
+                    cacheMetricSum('total_read_counts') != null && 
cacheMetricSum('total_read_counts') > 0.0
+        }
+
+        Double hitsRatio = cacheMetricMax('hits_ratio')
+        Double hitsRatio1h = cacheMetricMax('hits_ratio_1h')
+        Double hitsRatio5m = cacheMetricMax('hits_ratio_5m')
+        logger.info("Hit ratio metrics - hits_ratio: ${hitsRatio}, 
hits_ratio_1h: ${hitsRatio1h}, hits_ratio_5m: ${hitsRatio5m}")
+        assertTrue(hitsRatio > 0.0, HIT_RATIO_METRIC_FALSE_MSG)
+        assertTrue(hitsRatio1h > 0.0, HIT_RATIO_1H_METRIC_FALSE_MSG)
+        assertTrue(hitsRatio5m > 0.0, HIT_RATIO_5M_METRIC_FALSE_MSG)
+
+        Double normalQueueCurrSize = cacheMetricSum('normal_queue_curr_size')
+        Double normalQueueMaxSize = cacheMetricSum('normal_queue_max_size')
+        Double normalQueueCurrElements = 
cacheMetricSum('normal_queue_curr_elements')
+        Double normalQueueMaxElements = 
cacheMetricSum('normal_queue_max_elements')
+        Double indexQueueMaxSize = cacheMetricSum('index_queue_max_size')
+        Double ttlQueueMaxSize = cacheMetricSum('ttl_queue_max_size')
+        Double disposableQueueMaxSize = 
cacheMetricSum('disposable_queue_max_size')
+        Double cacheCapacity = (normalQueueMaxSize == null || 
indexQueueMaxSize == null ||
+                ttlQueueMaxSize == null || disposableQueueMaxSize == null) ? 
null :
+                normalQueueMaxSize + indexQueueMaxSize + ttlQueueMaxSize + 
disposableQueueMaxSize
+        logger.info("Normal queue metrics - curr_size: ${normalQueueCurrSize}, 
max_size: ${normalQueueMaxSize}, " +
+                "curr_elements: ${normalQueueCurrElements}, max_elements: 
${normalQueueMaxElements}")
+        logger.info("Total file cache capacity: ${cacheCapacity}")
+        // A queue's max_size is a soft limit. A queue may borrow unused 
capacity from
+        // other queues, while the total cache capacity remains the hard upper 
bound.
+        assertTrue(normalQueueCurrSize > 0.0 && cacheCapacity != null && 
normalQueueCurrSize <= cacheCapacity,
+                NORMAL_QUEUE_SIZE_VALIDATION_FAILED_MSG)
+        assertTrue(normalQueueCurrElements > 0.0, 
NORMAL_QUEUE_ELEMENTS_VALIDATION_FAILED_MSG)
+
+        Double initialHitCounts = cacheMetricSum('total_hit_counts')
+        Double initialReadCounts = cacheMetricSum('total_read_counts')
+        logger.info("Initial hit/read counts - hit_counts: 
${initialHitCounts}, read_counts: ${initialReadCounts}")
+
+        // Execute the same query to trigger cache operations
+        order_qt_2 querySql
+
+        awaitUntil(pollTimeoutSeconds, 1) {
+            Double updatedHitCounts = cacheMetricSum('total_hit_counts')
+            Double updatedReadCounts = cacheMetricSum('total_read_counts')
+            return updatedHitCounts != null && updatedHitCounts > 
initialHitCounts &&
+                    updatedReadCounts != null && updatedReadCounts > 
initialReadCounts
+        }
 
-    Double hitsRatio = cacheMetricMax('hits_ratio')
-    Double hitsRatio1h = cacheMetricMax('hits_ratio_1h')
-    Double hitsRatio5m = cacheMetricMax('hits_ratio_5m')
-    logger.info("Hit ratio metrics - hits_ratio: ${hitsRatio}, hits_ratio_1h: 
${hitsRatio1h}, hits_ratio_5m: ${hitsRatio5m}")
-    assertTrue(hitsRatio > 0.0, HIT_RATIO_METRIC_FALSE_MSG)
-    assertTrue(hitsRatio1h > 0.0, HIT_RATIO_1H_METRIC_FALSE_MSG)
-    assertTrue(hitsRatio5m > 0.0, HIT_RATIO_5M_METRIC_FALSE_MSG)
-
-    Double normalQueueCurrSize = cacheMetricSum('normal_queue_curr_size')
-    Double normalQueueMaxSize = cacheMetricSum('normal_queue_max_size')
-    Double normalQueueCurrElements = 
cacheMetricSum('normal_queue_curr_elements')
-    Double normalQueueMaxElements = cacheMetricSum('normal_queue_max_elements')
-    Double indexQueueMaxSize = cacheMetricSum('index_queue_max_size')
-    Double ttlQueueMaxSize = cacheMetricSum('ttl_queue_max_size')
-    Double disposableQueueMaxSize = cacheMetricSum('disposable_queue_max_size')
-    Double cacheCapacity = (normalQueueMaxSize == null || indexQueueMaxSize == 
null ||
-            ttlQueueMaxSize == null || disposableQueueMaxSize == null) ? null :
-            normalQueueMaxSize + indexQueueMaxSize + ttlQueueMaxSize + 
disposableQueueMaxSize
-    logger.info("Normal queue metrics - curr_size: ${normalQueueCurrSize}, 
max_size: ${normalQueueMaxSize}, " +
-            "curr_elements: ${normalQueueCurrElements}, max_elements: 
${normalQueueMaxElements}")
-    logger.info("Total file cache capacity: ${cacheCapacity}")
-    // A queue's max_size is a soft limit. A queue may borrow unused capacity 
from
-    // other queues, while the total cache capacity remains the hard upper 
bound.
-    assertTrue(normalQueueCurrSize > 0.0 && cacheCapacity != null && 
normalQueueCurrSize <= cacheCapacity,
-            NORMAL_QUEUE_SIZE_VALIDATION_FAILED_MSG)
-    assertTrue(normalQueueCurrElements > 0.0, 
NORMAL_QUEUE_ELEMENTS_VALIDATION_FAILED_MSG)
-
-    Double initialHitCounts = cacheMetricSum('total_hit_counts')
-    Double initialReadCounts = cacheMetricSum('total_read_counts')
-    logger.info("Initial hit/read counts - hit_counts: ${initialHitCounts}, 
read_counts: ${initialReadCounts}")
-
-    // Execute the same query to trigger cache operations
-    order_qt_2 querySql
-
-    awaitUntil(pollTimeoutSeconds, 1) {
         Double updatedHitCounts = cacheMetricSum('total_hit_counts')
         Double updatedReadCounts = cacheMetricSum('total_read_counts')
-        return updatedHitCounts != null && updatedHitCounts > initialHitCounts 
&&
-                updatedReadCounts != null && updatedReadCounts > 
initialReadCounts
-    }
 
-    Double updatedHitCounts = cacheMetricSum('total_hit_counts')
-    Double updatedReadCounts = cacheMetricSum('total_read_counts')
+        logger.info("Hit and read counts comparison - hit_counts: 
${initialHitCounts} -> " +
+                "${updatedHitCounts}, read_counts: ${initialReadCounts} -> 
${updatedReadCounts}")
 
-    logger.info("Hit and read counts comparison - hit_counts: 
${initialHitCounts} -> " +
-            "${updatedHitCounts}, read_counts: ${initialReadCounts} -> 
${updatedReadCounts}")
-
-    assertTrue(updatedHitCounts > initialHitCounts, 
TOTAL_HIT_COUNTS_DID_NOT_INCREASE_MSG)
-    assertTrue(updatedReadCounts > initialReadCounts, 
TOTAL_READ_COUNTS_DID_NOT_INCREASE_MSG)
-    return true
+        assertTrue(updatedHitCounts > initialHitCounts, 
TOTAL_HIT_COUNTS_DID_NOT_INCREASE_MSG)
+        assertTrue(updatedReadCounts > initialReadCounts, 
TOTAL_READ_COUNTS_DID_NOT_INCREASE_MSG)
+        return true
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to