sergehuber commented on code in PR #776:
URL: https://github.com/apache/unomi/pull/776#discussion_r3433750756


##########
services/src/test/java/org/apache/unomi/services/impl/TestConditionEvaluators.java:
##########
@@ -431,7 +423,7 @@ private static boolean evaluateCollectionCondition(Object 
actualValue, Condition
         switch (operator) {
             case "in": return actual.stream().anyMatch(expected::contains);
             case "inContains": return actual.stream().anyMatch(a ->
-                (a instanceof String) && expected.stream().anyMatch(b -> (b 
instanceof String) && ((String) a).contains((String) b)));
+                expected.stream().anyMatch(b -> ((String) a).contains((String) 
b)));
             case "notIn": return actual.stream().noneMatch(expected::contains);

Review Comment:
   Valid. The removal of `(a instanceof String)` and `(b instanceof String)` 
guards causes `ClassCastException` when the collection contains non-string 
elements. Restored the original guards.



##########
services/src/test/java/org/apache/unomi/services/impl/TestConditionEvaluators.java:
##########
@@ -532,13 +524,8 @@ private static ConditionEvaluator 
createPastEventConditionEvaluator() {
                 String key = (String) parameters.get("generatedPropertyKey");
                 tracer.trace(condition, "Using generated property key: " + 
key);
 
-                Object pastEventsObj = 
profile.getSystemProperties().get("pastEvents");
-                if (!(pastEventsObj instanceof List)) {
-                    tracer.trace(condition, "No pastEvents found in profile 
system properties");
-                    count = 0;
-                } else {
-                    @SuppressWarnings("unchecked")
-                    List<Map<String, Object>> pastEvents = (List<Map<String, 
Object>>) pastEventsObj;
+                List<Map<String, Object>> pastEvents = (ArrayList<Map<String, 
Object>>) profile.getSystemProperties().get("pastEvents");
+                if (pastEvents != null) {
                     tracer.trace(condition, "Found pastEvents in profile 
system properties");
                     Number l = (Number) pastEvents
                             .stream()

Review Comment:
   Valid. Casting directly to `ArrayList` throws `ClassCastException` if the 
stored value is any other `List` implementation, and also bypasses the original 
type-safety check. Restored the original `instanceof List` guard with a cast to 
`List<Map<String, Object>>`.



##########
services/src/test/java/org/apache/unomi/services/impl/TestConditionEvaluators.java:
##########
@@ -916,7 +906,7 @@ private static Parameter createParameterRecommended(String 
name, String type, St
     }
 
     public static Map<String, ConditionType> getConditionTypes() {
-        return Collections.unmodifiableMap(conditionTypes);
+        return conditionTypes;
     }

Review Comment:
   Valid. Returning the mutable backing map directly allows callers to 
accidentally modify shared state across tests. Restored 
`Collections.unmodifiableMap(conditionTypes)`.



##########
services/src/test/java/org/apache/unomi/services/impl/TestBundleContext.java:
##########
@@ -149,7 +148,7 @@ public <S> ServiceReference<S> getServiceReference(Class<S> 
clazz) {
 
     @Override
     public <S> Collection<ServiceReference<S>> getServiceReferences(Class<S> 
clazz, String filter) {
-        return Collections.emptyList();
+        return null;
     }

Review Comment:
   Valid. The OSGi `BundleContext` contract specifies an empty collection when 
no references exist, not null. Returning null can cause `NullPointerException` 
in production code under test that iterates over the result. Fixed to return 
`Collections.emptyList()`.



##########
services/src/test/java/org/apache/unomi/services/TestHelper.java:
##########
@@ -651,7 +796,7 @@ public static void cleanDefaultStorageDirectory(int 
maxRetries) {
                     return;
                 }
             } catch (IOException e) {
-                LOGGER.warn("Error deleting default storage directory, will 
retry", e);
+                LOGGER.warn("Error deleting default storage directory, will 
retry: {}", e.getMessage());
             }

Review Comment:
   Valid. Using `e.getMessage()` as a format argument loses the stack trace and 
exception chain, which makes intermittent CI failures harder to diagnose. 
Restored passing the `Throwable` directly as the last argument to 
`LOGGER.warn(...)` so SLF4J includes the full stack trace.



##########
services/src/test/java/org/apache/unomi/services/TestHelper.java:
##########
@@ -749,7 +894,7 @@ public static <T> T retryQueryUntilAvailable(Supplier<T> 
querySupplier, Integer
                 Thread.sleep(retryDelay);
             } catch (InterruptedException e) {
                 Thread.currentThread().interrupt();
-                throw new RuntimeException("Retry interrupted", e);
+                break;
             }

Review Comment:
   Valid. Breaking out of the loop and falling through to a generic timeout 
message hides the fact that the thread was interrupted, making failures caused 
by JUnit timeouts or test shutdown confusing. Restored the original behaviour: 
re-interrupt the thread and throw `new RuntimeException("Retry interrupted", 
e)`.



##########
services/src/test/java/org/apache/unomi/services/impl/segments/SegmentServiceImplTest.java:
##########
@@ -0,0 +1,1163 @@
+/*
+ * 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.
+ */
+package org.apache.unomi.services.impl.segments;
+
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.Metadata;
+import org.apache.unomi.api.PartialList;
+import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.actions.Action;
+import org.apache.unomi.api.conditions.Condition;
+import org.apache.unomi.api.conditions.ConditionType;
+import org.apache.unomi.api.exceptions.BadSegmentConditionException;
+import org.apache.unomi.api.rules.Rule;
+import org.apache.unomi.api.segments.Segment;
+import org.apache.unomi.api.segments.SegmentsAndScores;
+import org.apache.unomi.api.services.EventService;
+import org.apache.unomi.api.services.SchedulerService;
+import org.apache.unomi.api.services.cache.CacheableTypeConfig;
+import org.apache.unomi.persistence.spi.PersistenceService;
+import 
org.apache.unomi.persistence.spi.conditions.evaluator.ConditionEvaluatorDispatcher;
+import org.apache.unomi.services.TestHelper;
+import org.apache.unomi.services.common.security.ExecutionContextManagerImpl;
+import org.apache.unomi.services.common.security.KarafSecurityService;
+import org.apache.unomi.services.impl.InMemoryPersistenceServiceImpl;
+import org.apache.unomi.services.impl.TestConditionEvaluators;
+import org.apache.unomi.services.impl.TestEventAdmin;
+import org.apache.unomi.services.impl.TestTenantService;
+import org.apache.unomi.services.impl.cache.MultiTypeCacheServiceImpl;
+import org.apache.unomi.services.impl.definitions.DefinitionsServiceImpl;
+import org.apache.unomi.services.impl.events.EventServiceImpl;
+import org.apache.unomi.services.impl.rules.RulesServiceImpl;
+import org.apache.unomi.services.impl.rules.TestActionExecutorDispatcher;
+import org.apache.unomi.services.impl.rules.TestEvaluateProfileSegmentsAction;
+import org.apache.unomi.services.impl.rules.TestSetEventOccurrenceCountAction;
+import org.apache.unomi.tracing.api.RequestTracer;
+import org.apache.unomi.tracing.api.TracerService;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+import org.osgi.framework.BundleContext;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+public class SegmentServiceImplTest {
+
+    private SegmentServiceImpl segmentService;
+    private EventServiceImpl eventService;
+    private TestTenantService tenantService;
+    private PersistenceService persistenceService;
+    private DefinitionsServiceImpl definitionsService;
+    private MultiTypeCacheServiceImpl multiTypeCacheService;
+    private ExecutionContextManagerImpl executionContextManager;
+    private KarafSecurityService securityService;
+    private RulesServiceImpl rulesService;
+    private TestActionExecutorDispatcher actionExecutorDispatcher;
+
+    private BundleContext bundleContext;
+    private TracerService tracerService;
+    private RequestTracer requestTracer;
+
+    private SchedulerService schedulerService;
+
+    private static final String TENANT_1 = "tenant1";
+    private static final String TENANT_2 = "tenant2";
+    private static final String SYSTEM_TENANT = "system";
+
+    @BeforeEach
+    public void setUp() throws IOException {
+
+        tenantService = new TestTenantService();
+        securityService = TestHelper.createSecurityService();
+        executionContextManager = 
TestHelper.createExecutionContextManager(securityService);
+        TracerService tracerService = TestHelper.createTracerService();
+
+        // Create tenants using TestHelper
+        TestHelper.setupCommonTestData(tenantService);
+
+        ConditionEvaluatorDispatcher conditionEvaluatorDispatcher = 
TestConditionEvaluators.createDispatcher();
+
+        // Set up bundle context using TestHelper
+        bundleContext = TestHelper.createMockBundleContext();
+
+        persistenceService = new 
InMemoryPersistenceServiceImpl(executionContextManager, 
conditionEvaluatorDispatcher);
+
+        // Create scheduler service using TestHelper
+        schedulerService = 
TestHelper.createSchedulerService("segment-service-scheduler-node", 
persistenceService, executionContextManager, bundleContext, null, -1, true, 
true);
+
+        multiTypeCacheService = new MultiTypeCacheServiceImpl();
+
+        // Create definitions service with EventAdmin
+        java.util.Map.Entry<DefinitionsServiceImpl, TestEventAdmin> 
servicePair =
+            
TestHelper.createDefinitionServiceWithEventAdmin(persistenceService, 
bundleContext, schedulerService,
+                multiTypeCacheService, executionContextManager, tenantService);
+        definitionsService = servicePair.getKey();
+        TestEventAdmin testEventAdmin = servicePair.getValue();
+
+        // Inject definitionsService into the dispatcher
+        
TestHelper.injectDefinitionsServiceIntoDispatcher(conditionEvaluatorDispatcher, 
definitionsService);
+
+        TestConditionEvaluators.getConditionTypes().forEach((key, value) -> 
definitionsService.setConditionType(value));
+
+        // Set up event service using TestHelper
+        eventService = TestHelper.createEventService(persistenceService, 
bundleContext, definitionsService, tenantService, tracerService);
+        TestConditionEvaluators.setEventService(eventService);
+
+        // Set up action executor dispatcher
+        actionExecutorDispatcher = new 
TestActionExecutorDispatcher(definitionsService, persistenceService);
+        
actionExecutorDispatcher.setDefaultReturnValue(EventService.PROFILE_UPDATED);
+        actionExecutorDispatcher.setTracer(requestTracer);
+
+        // Set up rules service using TestHelper with EventAdmin
+        rulesService = TestHelper.createRulesService(persistenceService, 
bundleContext, schedulerService, definitionsService, eventService, 
executionContextManager, tenantService, multiTypeCacheService, 
actionExecutorDispatcher, testEventAdmin);
+        rulesService.setTracerService(tracerService);
+
+        // Set up segment service
+        segmentService = new SegmentServiceImpl();
+        segmentService.setBundleContext(bundleContext);
+        segmentService.setPersistenceService(persistenceService);
+        segmentService.setDefinitionsService(definitionsService);
+        segmentService.setRulesService(rulesService);
+        segmentService.setEventService(eventService);
+        segmentService.setContextManager(executionContextManager);
+        segmentService.setSchedulerService(schedulerService);
+        segmentService.setCacheService(multiTypeCacheService);
+        segmentService.setTenantService(tenantService);
+        segmentService.setTracerService(tracerService);
+
+        actionExecutorDispatcher.addExecutor("setEventOccurenceCountAction",
+                new TestSetEventOccurrenceCountAction(definitionsService, 
persistenceService));
+        actionExecutorDispatcher.addExecutor("evaluateProfileSegments",
+                new TestEvaluateProfileSegmentsAction(segmentService));
+
+        // Register TestEvaluateProfileSegmentsAction
+        actionExecutorDispatcher.addExecutor("evaluateProfileSegments", new 
TestEvaluateProfileSegmentsAction(segmentService));
+

Review Comment:
   Valid. The executor was registered twice in consecutive lines with separate 
`new TestEvaluateProfileSegmentsAction(segmentService)` instances, which is 
redundant and risks divergence in future edits. Removed the duplicate 
registration.



##########
services/src/test/java/org/apache/unomi/services/impl/rules/TestSetEventOccurrenceCountAction.java:
##########
@@ -32,7 +32,7 @@
 
 /**
  * Test implementation of the SetEventOccurrenceCountAction.
- * TODO: This is a duplicate of the SetEventOccurrenceCountAction in the 
unomi-plugins-base project to avoid introducing a dependency on it but should 
be cleaned up.
+ * @TODO This is a duplicate of the SetEventOccurrenceCountAction in the 
unomi-plugins-base project to avoid introducing a depending to it but should be 
cleaned up.
  */

Review Comment:
   Valid. `@TODO` is not a recognized Javadoc tag and can cause tooling 
warnings. Also "introducing a depending to it" was a grammatical error. Changed 
to `TODO:` (plain text) and corrected to "introducing a dependency on it".



-- 
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