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

wusheng pushed a commit to branch oal-v2
in repository https://gitbox.apache.org/repos/asf/skywalking.git

commit c5b61bb0f942ee40792e7333f757afb5621f1c1e
Author: Wu Sheng <[email protected]>
AuthorDate: Tue Feb 10 09:36:09 2026 +0800

    Add comprehensive filter verification tests for OAL V2
    
    Add tests to verify filter expressions are correctly processed and
    generated as runnable bytecode:
    - testFilterExpressionProcessing: Unit test for filter enrichment
    - testMetricsWithFilterGeneration: Full bytecode generation test
      using ServiceRelation source with single and multi-filter chains
    
    The tests verify:
    - Filter expressions are converted to template-ready format
    - Generated dispatcher classes load correctly in JVM
    - doMetrics methods with filter logic are generated
    - Metrics classes can be instantiated
    
    Co-Authored-By: Claude Opus 4.5 <[email protected]>
---
 .../oal/v2/generator/OALClassGeneratorV2Test.java  | 118 +++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git 
a/oap-server/oal-rt/src/test/java/org/apache/skywalking/oal/v2/generator/OALClassGeneratorV2Test.java
 
b/oap-server/oal-rt/src/test/java/org/apache/skywalking/oal/v2/generator/OALClassGeneratorV2Test.java
index ee5df06f31..49136fe7f9 100644
--- 
a/oap-server/oal-rt/src/test/java/org/apache/skywalking/oal/v2/generator/OALClassGeneratorV2Test.java
+++ 
b/oap-server/oal-rt/src/test/java/org/apache/skywalking/oal/v2/generator/OALClassGeneratorV2Test.java
@@ -38,6 +38,7 @@ import org.apache.skywalking.oap.server.core.oal.rt.OALDefine;
 import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
 import org.apache.skywalking.oap.server.core.source.Endpoint;
 import org.apache.skywalking.oap.server.core.source.Service;
+import org.apache.skywalking.oap.server.core.source.ServiceRelation;
 import org.apache.skywalking.oap.server.core.storage.StorageBuilderFactory;
 import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
 import org.junit.jupiter.api.BeforeAll;
@@ -71,6 +72,7 @@ public class OALClassGeneratorV2Test {
         DefaultScopeDefine.Listener listener = new 
DefaultScopeDefine.Listener();
         listener.notify(Service.class);
         listener.notify(Endpoint.class);
+        listener.notify(ServiceRelation.class);
     }
 
     /**
@@ -270,6 +272,122 @@ public class OALClassGeneratorV2Test {
         assertNotNull(findMethodByName(dispatcherClass, "doEndpointCalls"));
     }
 
+    /**
+     * Test that filter expressions are correctly processed by the enricher.
+     * This is a unit test for filter processing - doesn't generate bytecode.
+     */
+    @Test
+    public void testFilterExpressionProcessing() throws Exception {
+        // OAL with filter expression
+        String oal = "test_sla = from(Endpoint.*).filter(status == 
true).percent(status == true);";
+
+        MetricDefinitionEnricher enricher = new 
MetricDefinitionEnricher(SOURCE_PACKAGE, METRICS_PACKAGE);
+
+        // Parse and enrich
+        OALScriptParserV2 parser = OALScriptParserV2.parse(oal);
+        MetricDefinition metric = parser.getMetrics().get(0);
+        CodeGenModel model = enricher.enrich(metric);
+
+        // Verify filter expressions are converted to template-ready format
+        assertFalse(model.getFilterExpressions().isEmpty(),
+            "Filter expressions should be populated");
+        assertEquals(1, model.getFilterExpressions().size());
+
+        CodeGenModel.FilterExpressionV2 filterExpr = 
model.getFilterExpressions().get(0);
+        assertNotNull(filterExpr.getExpressionObject(), "Expression object 
should not be null");
+        assertTrue(filterExpr.getExpressionObject().contains("Match"),
+            "Expression object should be a matcher class (e.g., EqualMatch, 
NotEqualMatch)");
+        assertNotNull(filterExpr.getLeft(), "Left side should not be null");
+        assertTrue(filterExpr.getLeft().contains("source."),
+            "Left side should reference source");
+        assertNotNull(filterExpr.getRight(), "Right side should not be null");
+    }
+
+    /**
+     * Test full code generation for metrics with filter expressions.
+     * Uses ServiceRelation source to avoid frozen class conflicts with other 
tests.
+     *
+     * This test validates:
+     * - Filter expressions are correctly passed to templates
+     * - Generated dispatcher contains filter logic
+     * - Multiple filters in chain are handled correctly
+     */
+    @Test
+    public void testMetricsWithFilterGeneration() throws Exception {
+        // OAL with various filter types from core.oal
+        String oal = "service_relation_client_cpm = 
from(ServiceRelation.*).filter(detectPoint == DetectPoint.CLIENT).cpm();\n" +
+            "service_relation_server_cpm = 
from(ServiceRelation.*).filter(detectPoint == DetectPoint.SERVER).cpm();\n" +
+            "service_relation_client_call_sla = 
from(ServiceRelation.*).filter(detectPoint == DetectPoint.CLIENT).filter(status 
== true).percent(status == true);\n" +
+            "service_relation_client_resp_time = 
from(ServiceRelation.latency).filter(detectPoint == 
DetectPoint.CLIENT).longAvg();";
+
+        OALClassGeneratorV2 generator = createGenerator();
+        MetricDefinitionEnricher enricher = new 
MetricDefinitionEnricher(SOURCE_PACKAGE, METRICS_PACKAGE);
+
+        List<Class> metricsClasses = new ArrayList<>();
+        List<Class> dispatcherClasses = new ArrayList<>();
+
+        generateClasses(oal, generator, enricher, metricsClasses, 
dispatcherClasses);
+
+        // Verify 4 metrics classes generated
+        assertEquals(4, metricsClasses.size());
+
+        // Verify 1 dispatcher class for ServiceRelation source
+        assertEquals(1, dispatcherClasses.size());
+
+        Class<?> dispatcherClass = dispatcherClasses.get(0);
+        assertEquals("ServiceRelationDispatcher", 
dispatcherClass.getSimpleName());
+        assertTrue(SourceDispatcher.class.isAssignableFrom(dispatcherClass));
+
+        // Verify all doMetrics methods exist
+        Method doClientCpm = findMethodByName(dispatcherClass, 
"doServiceRelationClientCpm");
+        Method doServerCpm = findMethodByName(dispatcherClass, 
"doServiceRelationServerCpm");
+        Method doClientCallSla = findMethodByName(dispatcherClass, 
"doServiceRelationClientCallSla");
+        Method doClientRespTime = findMethodByName(dispatcherClass, 
"doServiceRelationClientRespTime");
+
+        assertNotNull(doClientCpm, "doServiceRelationClientCpm should be 
generated");
+        assertNotNull(doServerCpm, "doServiceRelationServerCpm should be 
generated");
+        assertNotNull(doClientCallSla, "doServiceRelationClientCallSla should 
be generated");
+        assertNotNull(doClientRespTime, "doServiceRelationClientRespTime 
should be generated");
+
+        // Verify filter expressions were correctly enriched
+        OALScriptParserV2 parser = OALScriptParserV2.parse(oal);
+
+        // Check single filter metric
+        MetricDefinition clientCpmMetric = parser.getMetrics().get(0);
+        CodeGenModel clientCpmModel = enricher.enrich(clientCpmMetric);
+        assertEquals(1, clientCpmModel.getFilterExpressions().size());
+        
assertTrue(clientCpmModel.getFilterExpressions().get(0).getExpressionObject().contains("Match"));
+        
assertTrue(clientCpmModel.getFilterExpressions().get(0).getLeft().contains("getDetectPoint"));
+        
assertTrue(clientCpmModel.getFilterExpressions().get(0).getRight().contains("DetectPoint.CLIENT"));
+
+        // Check multi-filter metric (filter chain)
+        MetricDefinition clientCallSlaMetric = parser.getMetrics().get(2);
+        CodeGenModel clientCallSlaModel = enricher.enrich(clientCallSlaMetric);
+        assertEquals(2, clientCallSlaModel.getFilterExpressions().size(),
+            "Multi-filter metric should have 2 filter expressions");
+
+        // First filter: detectPoint == DetectPoint.CLIENT
+        CodeGenModel.FilterExpressionV2 filter1 = 
clientCallSlaModel.getFilterExpressions().get(0);
+        assertTrue(filter1.getLeft().contains("getDetectPoint"));
+
+        // Second filter: status == true (boolean)
+        CodeGenModel.FilterExpressionV2 filter2 = 
clientCallSlaModel.getFilterExpressions().get(1);
+        assertTrue(filter2.getLeft().contains("isStatus") || 
filter2.getLeft().contains("getStatus"));
+        assertEquals("true", filter2.getRight());
+
+        // Verify metrics classes are properly generated
+        Class<?> clientCpmClass = findClassBySimpleName(metricsClasses, 
"ServiceRelationClientCpmMetrics");
+        Class<?> slaClass = findClassBySimpleName(metricsClasses, 
"ServiceRelationClientCallSlaMetrics");
+
+        assertNotNull(clientCpmClass);
+        assertNotNull(slaClass);
+
+        // Test instantiation
+        Object clientCpmInstance = 
clientCpmClass.getDeclaredConstructor().newInstance();
+        assertNotNull(clientCpmInstance);
+        assertTrue(clientCpmInstance instanceof Metrics);
+    }
+
     /**
      * Create a configured OALClassGeneratorV2 instance.
      */

Reply via email to