RockteMQ-AI commented on code in PR #3578:
URL: 
https://github.com/apache/rocketmq-dashboard/pull/3578#discussion_r3941684373


##########
server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleEvaluatorTest.java:
##########
@@ -21,71 +21,142 @@
 import org.junit.jupiter.api.Test;
 
 import java.time.Instant;
+import java.util.Map;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class AlertRuleEvaluatorTest {
+
     private final AlertRuleEvaluator evaluator = new AlertRuleEvaluator();
 
+    private AlertRuleVO rule(String metric, AlertDomain domain, String 
operator, double threshold) {
+        return AlertRuleVO.builder()
+            .domain(domain)
+            .metric(metric)
+            .operator(operator)
+            .threshold(threshold)
+            .duration("5m")
+            .build();
+    }
+
+    private MetricSample sample(String metricKey, AlertDomain domain, double 
value) {
+        return new MetricSample(metricKey, domain, "inst-1", "cluster-1", 
Map.of(),
+                value, MetricAvailability.AVAILABLE, 
Instant.parse("2026-09-01T08:00:00Z"));
+    }
+
+    private MetricSample unavailableSample(String metricKey, AlertDomain 
domain) {
+        return new MetricSample(metricKey, domain, "inst-1", "cluster-1", 
Map.of(),
+                null, MetricAvailability.UNAVAILABLE, 
Instant.parse("2026-09-01T08:00:00Z"));
+    }
+
     @Test
-    void triggersMatchingAvailableMetricTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                .operator(">=").threshold(0.85).enabled(true).build();
-        MetricSample sample = sample(MetricAvailability.AVAILABLE, 0.9);
+    void mismatchingMetricDoesNotMatch() {
+        AlertEvaluationResult result = evaluator.evaluate(
+                rule("broker.disk.usage_ratio", AlertDomain.CLUSTER, ">", 0.8),
+                sample("broker.cpu.usage", AlertDomain.CLUSTER, 0.9));
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, sample);
+        assertFalse(result.matches());
+        assertEquals(MetricAvailability.AVAILABLE, result.availability());
+    }
+
+    @Test
+    void mismatchingDomainDoesNotMatch() {
+        AlertEvaluationResult result = evaluator.evaluate(
+                rule("consumer.lag.total", AlertDomain.BUSINESS, ">", 100),
+                sample("consumer.lag.total", AlertDomain.CLUSTER, 500));
 
-        assertThat(result.matches()).isTrue();
-        assertThat(result.conditionMet()).isTrue();
-        assertThat(result.currentValue()).isEqualTo(0.9);
+        assertFalse(result.matches());
     }
 
     @Test
-    void evaluatesPercentageThresholdsForNativeRatioMetricsTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                
.operator(">=").threshold(85).thresholdUnit("%").enabled(true).build();
+    void unavailableSampleOnlyMatchesUnavailableOperator() {
+        AlertEvaluationResult matched = evaluator.evaluate(
+                rule("broker.availability", AlertDomain.CLUSTER, 
"UNAVAILABLE", 0),
+                unavailableSample("broker.availability", AlertDomain.CLUSTER));
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, 
sample(MetricAvailability.AVAILABLE, 0.9));
+        assertTrue(matched.matches());
+        assertTrue(matched.conditionMet());
+        assertNull(matched.currentValue());
 

Review Comment:
   currentValue() propagation for AVAILABLE samples is no longer asserted 
anywhere. The deleted triggersMatchingAvailableMetricTest asserted 
currentValue() == 0.9; the only remaining currentValue assertion is assertNull 
for the unavailable case. If AlertRuleEvaluator stopped returning the sample 
value as currentValue (AlertRuleEvaluator.java:40-42), every test still passes 
and alert notifications lose their 'current value' payload. Consider asserting 
currentValue in greaterThanComparesAgainstThreshold (e.g. is 0.9 / 0.7 for the 
two evaluations).



##########
server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleEvaluatorTest.java:
##########
@@ -21,71 +21,142 @@
 import org.junit.jupiter.api.Test;
 
 import java.time.Instant;
+import java.util.Map;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class AlertRuleEvaluatorTest {
+
     private final AlertRuleEvaluator evaluator = new AlertRuleEvaluator();
 
+    private AlertRuleVO rule(String metric, AlertDomain domain, String 
operator, double threshold) {
+        return AlertRuleVO.builder()
+            .domain(domain)
+            .metric(metric)
+            .operator(operator)
+            .threshold(threshold)
+            .duration("5m")
+            .build();
+    }
+
+    private MetricSample sample(String metricKey, AlertDomain domain, double 
value) {
+        return new MetricSample(metricKey, domain, "inst-1", "cluster-1", 
Map.of(),
+                value, MetricAvailability.AVAILABLE, 
Instant.parse("2026-09-01T08:00:00Z"));
+    }
+
+    private MetricSample unavailableSample(String metricKey, AlertDomain 
domain) {
+        return new MetricSample(metricKey, domain, "inst-1", "cluster-1", 
Map.of(),
+                null, MetricAvailability.UNAVAILABLE, 
Instant.parse("2026-09-01T08:00:00Z"));
+    }
+
     @Test
-    void triggersMatchingAvailableMetricTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                .operator(">=").threshold(0.85).enabled(true).build();
-        MetricSample sample = sample(MetricAvailability.AVAILABLE, 0.9);
+    void mismatchingMetricDoesNotMatch() {
+        AlertEvaluationResult result = evaluator.evaluate(
+                rule("broker.disk.usage_ratio", AlertDomain.CLUSTER, ">", 0.8),
+                sample("broker.cpu.usage", AlertDomain.CLUSTER, 0.9));
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, sample);
+        assertFalse(result.matches());
+        assertEquals(MetricAvailability.AVAILABLE, result.availability());
+    }
+
+    @Test
+    void mismatchingDomainDoesNotMatch() {
+        AlertEvaluationResult result = evaluator.evaluate(
+                rule("consumer.lag.total", AlertDomain.BUSINESS, ">", 100),
+                sample("consumer.lag.total", AlertDomain.CLUSTER, 500));
 
-        assertThat(result.matches()).isTrue();
-        assertThat(result.conditionMet()).isTrue();
-        assertThat(result.currentValue()).isEqualTo(0.9);
+        assertFalse(result.matches());
     }
 
     @Test
-    void evaluatesPercentageThresholdsForNativeRatioMetricsTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                
.operator(">=").threshold(85).thresholdUnit("%").enabled(true).build();
+    void unavailableSampleOnlyMatchesUnavailableOperator() {
+        AlertEvaluationResult matched = evaluator.evaluate(
+                rule("broker.availability", AlertDomain.CLUSTER, 
"UNAVAILABLE", 0),
+                unavailableSample("broker.availability", AlertDomain.CLUSTER));
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, 
sample(MetricAvailability.AVAILABLE, 0.9));
+        assertTrue(matched.matches());
+        assertTrue(matched.conditionMet());
+        assertNull(matched.currentValue());
 
-        assertThat(result.conditionMet()).isTrue();
+        AlertEvaluationResult notMatched = evaluator.evaluate(
+                rule("broker.availability", AlertDomain.CLUSTER, ">", 0),
+                unavailableSample("broker.availability", AlertDomain.CLUSTER));
+
+        assertTrue(notMatched.matches());
+        assertFalse(notMatched.conditionMet());
     }
 
     @Test
-    void unavailableMetricDoesNotBehaveAsZeroTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                .operator("<").threshold(0.1).enabled(true).build();
+    void greaterThanComparesAgainstThreshold() {
+        AlertRuleVO rule = rule("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, ">", 0.8);

Review Comment:
   Coverage regression: the deleted 
evaluatesPercentageThresholdsForNativeRatioMetricsTest was the only test 
verifying that evaluate() applies 
AlertRuleSemanticFingerprint.normalizedThreshold() (AlertRuleEvaluator.java:41) 
before comparing. AlertRuleSemanticFingerprintTest only checks fingerprint 
identity, not evaluation. After this PR, replacing normalizedThreshold(rule) 
with rule.getThreshold() would pass the entire suite, and a rule with threshold 
85 + thresholdUnit "%" on broker.disk.usage_ratio would compare 85 against a 
0.9 ratio and never fire. Please re-add a test like: rule(metric, domain, ">=", 
85) with .thresholdUnit("%") against a 0.9 sample asserting conditionMet() — 
the PR description itself says the tests pin comparison 'against the normalized 
threshold', so this path should be pinned.



##########
server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleEvaluatorTest.java:
##########
@@ -21,71 +21,142 @@
 import org.junit.jupiter.api.Test;
 
 import java.time.Instant;
+import java.util.Map;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class AlertRuleEvaluatorTest {
+
     private final AlertRuleEvaluator evaluator = new AlertRuleEvaluator();
 
+    private AlertRuleVO rule(String metric, AlertDomain domain, String 
operator, double threshold) {
+        return AlertRuleVO.builder()
+            .domain(domain)
+            .metric(metric)
+            .operator(operator)
+            .threshold(threshold)
+            .duration("5m")
+            .build();
+    }
+
+    private MetricSample sample(String metricKey, AlertDomain domain, double 
value) {
+        return new MetricSample(metricKey, domain, "inst-1", "cluster-1", 
Map.of(),
+                value, MetricAvailability.AVAILABLE, 
Instant.parse("2026-09-01T08:00:00Z"));
+    }
+
+    private MetricSample unavailableSample(String metricKey, AlertDomain 
domain) {
+        return new MetricSample(metricKey, domain, "inst-1", "cluster-1", 
Map.of(),
+                null, MetricAvailability.UNAVAILABLE, 
Instant.parse("2026-09-01T08:00:00Z"));
+    }
+
     @Test
-    void triggersMatchingAvailableMetricTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                .operator(">=").threshold(0.85).enabled(true).build();
-        MetricSample sample = sample(MetricAvailability.AVAILABLE, 0.9);
+    void mismatchingMetricDoesNotMatch() {
+        AlertEvaluationResult result = evaluator.evaluate(
+                rule("broker.disk.usage_ratio", AlertDomain.CLUSTER, ">", 0.8),
+                sample("broker.cpu.usage", AlertDomain.CLUSTER, 0.9));
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, sample);
+        assertFalse(result.matches());
+        assertEquals(MetricAvailability.AVAILABLE, result.availability());
+    }
+
+    @Test
+    void mismatchingDomainDoesNotMatch() {
+        AlertEvaluationResult result = evaluator.evaluate(
+                rule("consumer.lag.total", AlertDomain.BUSINESS, ">", 100),
+                sample("consumer.lag.total", AlertDomain.CLUSTER, 500));
 
-        assertThat(result.matches()).isTrue();
-        assertThat(result.conditionMet()).isTrue();
-        assertThat(result.currentValue()).isEqualTo(0.9);
+        assertFalse(result.matches());
     }
 
     @Test
-    void evaluatesPercentageThresholdsForNativeRatioMetricsTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                
.operator(">=").threshold(85).thresholdUnit("%").enabled(true).build();
+    void unavailableSampleOnlyMatchesUnavailableOperator() {
+        AlertEvaluationResult matched = evaluator.evaluate(
+                rule("broker.availability", AlertDomain.CLUSTER, 
"UNAVAILABLE", 0),
+                unavailableSample("broker.availability", AlertDomain.CLUSTER));
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, 
sample(MetricAvailability.AVAILABLE, 0.9));
+        assertTrue(matched.matches());
+        assertTrue(matched.conditionMet());
+        assertNull(matched.currentValue());
 
-        assertThat(result.conditionMet()).isTrue();
+        AlertEvaluationResult notMatched = evaluator.evaluate(
+                rule("broker.availability", AlertDomain.CLUSTER, ">", 0),
+                unavailableSample("broker.availability", AlertDomain.CLUSTER));
+
+        assertTrue(notMatched.matches());
+        assertFalse(notMatched.conditionMet());
     }
 
     @Test
-    void unavailableMetricDoesNotBehaveAsZeroTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                .operator("<").threshold(0.1).enabled(true).build();
+    void greaterThanComparesAgainstThreshold() {
+        AlertRuleVO rule = rule("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, ">", 0.8);
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, 
sample(MetricAvailability.UNAVAILABLE, null));
+        assertTrue(evaluator.evaluate(rule, sample("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, 0.9))
+                .conditionMet());
+        assertFalse(evaluator.evaluate(rule, sample("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, 0.7))
+                .conditionMet());
+    }
 
-        assertThat(result.matches()).isTrue();
-        assertThat(result.conditionMet()).isFalse();
-        assertThat(result.currentValue()).isNull();
+    @Test
+    void equalityOperatorUsesDoubleCompare() {
+        AlertRuleVO rule = rule("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, "==", 0.8);

Review Comment:
   Operator coverage regression: the old suite exercised ">=" (two tests) and 
"<" (one test); the new suite only covers ">", "==", and "!=". Three of the six 
numeric cases in AlertRuleEvaluator.compare() (AlertRuleEvaluator.java:54-57: 
>=, <, <=) are now untested, so an off-by-one typo like case ">=" -> value > 
threshold would go undetected. This also contradicts the PR description's claim 
that the tests pin 'every comparison operator'. Please add cases for ">=", "<", 
and "<=", ideally including boundary samples (value == threshold).



##########
server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleEvaluatorTest.java:
##########
@@ -21,71 +21,142 @@
 import org.junit.jupiter.api.Test;
 
 import java.time.Instant;
+import java.util.Map;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class AlertRuleEvaluatorTest {

Review Comment:
   PR description inaccuracy: the summary says this 'adds the first dedicated 
unit test suite for AlertRuleEvaluator', but the diff replaces an existing 
5-test suite (index b55fa7c1c..e6ef8e388). This is a rewrite, not an addition, 
and it nets a loss of unique coverage (see findings above). Please update the 
description so maintainers can see this is a coverage swap and judge the 
trade-offs.



##########
server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleEvaluatorTest.java:
##########
@@ -21,71 +21,142 @@
 import org.junit.jupiter.api.Test;
 
 import java.time.Instant;
+import java.util.Map;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class AlertRuleEvaluatorTest {
+
     private final AlertRuleEvaluator evaluator = new AlertRuleEvaluator();
 
+    private AlertRuleVO rule(String metric, AlertDomain domain, String 
operator, double threshold) {
+        return AlertRuleVO.builder()
+            .domain(domain)
+            .metric(metric)
+            .operator(operator)
+            .threshold(threshold)
+            .duration("5m")
+            .build();
+    }
+
+    private MetricSample sample(String metricKey, AlertDomain domain, double 
value) {
+        return new MetricSample(metricKey, domain, "inst-1", "cluster-1", 
Map.of(),
+                value, MetricAvailability.AVAILABLE, 
Instant.parse("2026-09-01T08:00:00Z"));
+    }
+
+    private MetricSample unavailableSample(String metricKey, AlertDomain 
domain) {
+        return new MetricSample(metricKey, domain, "inst-1", "cluster-1", 
Map.of(),
+                null, MetricAvailability.UNAVAILABLE, 
Instant.parse("2026-09-01T08:00:00Z"));
+    }
+
     @Test
-    void triggersMatchingAvailableMetricTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                .operator(">=").threshold(0.85).enabled(true).build();
-        MetricSample sample = sample(MetricAvailability.AVAILABLE, 0.9);
+    void mismatchingMetricDoesNotMatch() {
+        AlertEvaluationResult result = evaluator.evaluate(
+                rule("broker.disk.usage_ratio", AlertDomain.CLUSTER, ">", 0.8),
+                sample("broker.cpu.usage", AlertDomain.CLUSTER, 0.9));
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, sample);
+        assertFalse(result.matches());
+        assertEquals(MetricAvailability.AVAILABLE, result.availability());
+    }
+
+    @Test
+    void mismatchingDomainDoesNotMatch() {
+        AlertEvaluationResult result = evaluator.evaluate(
+                rule("consumer.lag.total", AlertDomain.BUSINESS, ">", 100),
+                sample("consumer.lag.total", AlertDomain.CLUSTER, 500));
 
-        assertThat(result.matches()).isTrue();
-        assertThat(result.conditionMet()).isTrue();
-        assertThat(result.currentValue()).isEqualTo(0.9);
+        assertFalse(result.matches());
     }
 
     @Test
-    void evaluatesPercentageThresholdsForNativeRatioMetricsTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                
.operator(">=").threshold(85).thresholdUnit("%").enabled(true).build();
+    void unavailableSampleOnlyMatchesUnavailableOperator() {
+        AlertEvaluationResult matched = evaluator.evaluate(
+                rule("broker.availability", AlertDomain.CLUSTER, 
"UNAVAILABLE", 0),
+                unavailableSample("broker.availability", AlertDomain.CLUSTER));
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, 
sample(MetricAvailability.AVAILABLE, 0.9));
+        assertTrue(matched.matches());
+        assertTrue(matched.conditionMet());
+        assertNull(matched.currentValue());
 
-        assertThat(result.conditionMet()).isTrue();
+        AlertEvaluationResult notMatched = evaluator.evaluate(
+                rule("broker.availability", AlertDomain.CLUSTER, ">", 0),
+                unavailableSample("broker.availability", AlertDomain.CLUSTER));
+
+        assertTrue(notMatched.matches());
+        assertFalse(notMatched.conditionMet());
     }
 
     @Test
-    void unavailableMetricDoesNotBehaveAsZeroTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                .operator("<").threshold(0.1).enabled(true).build();
+    void greaterThanComparesAgainstThreshold() {
+        AlertRuleVO rule = rule("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, ">", 0.8);
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, 
sample(MetricAvailability.UNAVAILABLE, null));
+        assertTrue(evaluator.evaluate(rule, sample("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, 0.9))
+                .conditionMet());
+        assertFalse(evaluator.evaluate(rule, sample("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, 0.7))
+                .conditionMet());
+    }
 
-        assertThat(result.matches()).isTrue();
-        assertThat(result.conditionMet()).isFalse();
-        assertThat(result.currentValue()).isNull();
+    @Test
+    void equalityOperatorUsesDoubleCompare() {
+        AlertRuleVO rule = rule("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, "==", 0.8);
+
+        assertTrue(evaluator.evaluate(rule, sample("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, 0.8))
+                .conditionMet());
+        assertFalse(evaluator.evaluate(rule, sample("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, 0.81))
+                .conditionMet());
     }
 
     @Test
-    void explicitlyTriggersAvailabilityRuleForUnavailableSampleTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.availability")
-                .operator("UNAVAILABLE").enabled(true).build();
-        MetricSample sample = new MetricSample("broker.availability", 
AlertDomain.CLUSTER, "local", null, null,
-                null, MetricAvailability.UNAVAILABLE, Instant.now());
+    void notEqualsOperatorDetectsDifference() {
+        AlertRuleVO rule = rule("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, "!=", 0.8);
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, sample);
+        assertTrue(evaluator.evaluate(rule, sample("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, 0.81))
+                .conditionMet());
+        assertFalse(evaluator.evaluate(rule, sample("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, 0.8))
+                .conditionMet());
+    }
 
-        assertThat(result.matches()).isTrue();
-        assertThat(result.conditionMet()).isTrue();
-        assertThat(result.currentValue()).isNull();
+    @Test
+    void unknownOrNullOperatorNeverMatches() {
+        AlertRuleVO unknown = rule("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, "~", 0.8);
+        assertFalse(evaluator.evaluate(unknown, 
sample("broker.disk.usage_ratio", AlertDomain.CLUSTER, 0.9))
+                .conditionMet());
+
+        AlertRuleVO nullOp = rule("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, null, 0.8);
+        assertFalse(evaluator.evaluate(nullOp, 
sample("broker.disk.usage_ratio", AlertDomain.CLUSTER, 0.9))
+                .conditionMet());
     }
 
     @Test
-    void doesNotMatchOtherRuleDomainTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.BUSINESS).metric("broker.disk.usage_ratio")
-                .operator(">=").threshold(0.85).enabled(true).build();
+    void nullRuleOrSampleDoesNotMatch() {
+        AlertEvaluationResult noRule = evaluator.evaluate(null,
+                sample("broker.disk.usage_ratio", AlertDomain.CLUSTER, 0.9));
+
+        assertFalse(noRule.matches());
+        assertEquals(MetricAvailability.AVAILABLE, noRule.availability());
 
-        assertThat(evaluator.evaluate(rule, 
sample(MetricAvailability.AVAILABLE, 0.9)).matches()).isFalse();
+        AlertEvaluationResult noSample = evaluator.evaluate(
+                rule("broker.disk.usage_ratio", AlertDomain.CLUSTER, ">", 
0.8), null);
+
+        assertFalse(noSample.matches());
+        assertNull(noSample.availability());
     }
 
-    private static MetricSample sample(MetricAvailability availability, Double 
value) {
-        return new MetricSample("broker.disk.usage_ratio", 
AlertDomain.CLUSTER, "local", null, null, value,
-                availability, Instant.now());
+    @Test
+    void nullDomainDefaultsToBusiness() {
+        AlertRuleVO rule = AlertRuleVO.builder()

Review Comment:
   nullDomainDefaultsToBusiness does not exercise the evaluator's null-domain 
fallback. AlertRuleVO declares @Builder.Default private AlertDomain domain = 
AlertDomain.BUSINESS (AlertRuleVO.java:32-33), so builder().metric(...).build() 
produces domain == BUSINESS, not null, and AlertRuleEvaluator.ruleDomain()'s 
null branch (AlertRuleEvaluator.java:45-47) is never reached. The test 
currently validates the Lombok default, not the evaluator behavior in its name. 
Pass the null explicitly, e.g. 
AlertRuleVO.builder().domain(null).metric(...)... — or alternatively via new 
AlertRuleVO() plus setters with domain left null.



##########
server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleEvaluatorTest.java:
##########
@@ -21,71 +21,142 @@
 import org.junit.jupiter.api.Test;
 
 import java.time.Instant;
+import java.util.Map;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;

Review Comment:
   Style consistency: 24 of the 32 test files in this package use AssertJ 
(assertThat(...).isTrue() etc.), and this file previously did too. The rewrite 
switches to raw JUnit 5 Assertions, going against the package convention. Not 
blocking, but keeping AssertJ would preserve consistency and give better 
failure messages (e.g. assertEquals(0.9, result.currentValue()) would print 
both values).



##########
server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertRuleEvaluatorTest.java:
##########
@@ -21,71 +21,142 @@
 import org.junit.jupiter.api.Test;
 
 import java.time.Instant;
+import java.util.Map;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class AlertRuleEvaluatorTest {
+
     private final AlertRuleEvaluator evaluator = new AlertRuleEvaluator();
 
+    private AlertRuleVO rule(String metric, AlertDomain domain, String 
operator, double threshold) {
+        return AlertRuleVO.builder()
+            .domain(domain)
+            .metric(metric)
+            .operator(operator)
+            .threshold(threshold)
+            .duration("5m")
+            .build();
+    }
+
+    private MetricSample sample(String metricKey, AlertDomain domain, double 
value) {
+        return new MetricSample(metricKey, domain, "inst-1", "cluster-1", 
Map.of(),
+                value, MetricAvailability.AVAILABLE, 
Instant.parse("2026-09-01T08:00:00Z"));
+    }
+
+    private MetricSample unavailableSample(String metricKey, AlertDomain 
domain) {
+        return new MetricSample(metricKey, domain, "inst-1", "cluster-1", 
Map.of(),
+                null, MetricAvailability.UNAVAILABLE, 
Instant.parse("2026-09-01T08:00:00Z"));
+    }
+
     @Test
-    void triggersMatchingAvailableMetricTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                .operator(">=").threshold(0.85).enabled(true).build();
-        MetricSample sample = sample(MetricAvailability.AVAILABLE, 0.9);
+    void mismatchingMetricDoesNotMatch() {
+        AlertEvaluationResult result = evaluator.evaluate(
+                rule("broker.disk.usage_ratio", AlertDomain.CLUSTER, ">", 0.8),
+                sample("broker.cpu.usage", AlertDomain.CLUSTER, 0.9));
 
-        AlertEvaluationResult result = evaluator.evaluate(rule, sample);
+        assertFalse(result.matches());
+        assertEquals(MetricAvailability.AVAILABLE, result.availability());
+    }
+
+    @Test
+    void mismatchingDomainDoesNotMatch() {
+        AlertEvaluationResult result = evaluator.evaluate(
+                rule("consumer.lag.total", AlertDomain.BUSINESS, ">", 100),
+                sample("consumer.lag.total", AlertDomain.CLUSTER, 500));
 
-        assertThat(result.matches()).isTrue();
-        assertThat(result.conditionMet()).isTrue();
-        assertThat(result.currentValue()).isEqualTo(0.9);
+        assertFalse(result.matches());
     }
 
     @Test
-    void evaluatesPercentageThresholdsForNativeRatioMetricsTest() {
-        AlertRuleVO rule = 
AlertRuleVO.builder().domain(AlertDomain.CLUSTER).metric("broker.disk.usage_ratio")
-                
.operator(">=").threshold(85).thresholdUnit("%").enabled(true).build();
+    void unavailableSampleOnlyMatchesUnavailableOperator() {
+        AlertEvaluationResult matched = evaluator.evaluate(

Review Comment:
   Optional: MetricAvailability has four values (AVAILABLE, UNAVAILABLE, 
UNSUPPORTED, STALE) and the evaluator routes all non-AVAILABLE samples through 
the same branch (AlertRuleEvaluator.java:34-38: matches()=true, 
conditionMet()=false unless operator is UNAVAILABLE and availability is 
UNAVAILABLE). Only UNAVAILABLE is tested. A one-line case with a STALE or 
UNSUPPORTED sample would pin that these also never satisfy a numeric operator — 
a pre-existing gap, fine to address here or separately.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to