From 1e48f7806eeaecfbae1d2438c9c7d22d7078fdcb Mon Sep 17 00:00:00 2001
From: Fotis Soldatos <fsoldatos@ubitech.eu>
Date: Fri, 5 Aug 2022 00:52:11 +0300
Subject: [PATCH] refactor(policy): add validation at PolicyRuleDevice

---
 .../policy/model/PolicyRuleDevice.java        |   6 +
 .../policy/PolicyRuleBasicValidationTest.java |   2 +-
 .../PolicyRuleDeviceValidationTest.java       | 178 ++++++++++++++++++
 .../eu/teraflow/policy/PolicyServiceTest.java |  17 +-
 src/policy/target/kubernetes/kubernetes.yml   |  28 +--
 5 files changed, 215 insertions(+), 16 deletions(-)
 create mode 100644 src/policy/src/test/java/eu/teraflow/policy/PolicyRuleDeviceValidationTest.java

diff --git a/src/policy/src/main/java/eu/teraflow/policy/model/PolicyRuleDevice.java b/src/policy/src/main/java/eu/teraflow/policy/model/PolicyRuleDevice.java
index 46151ea5c..6dbbe2e00 100644
--- a/src/policy/src/main/java/eu/teraflow/policy/model/PolicyRuleDevice.java
+++ b/src/policy/src/main/java/eu/teraflow/policy/model/PolicyRuleDevice.java
@@ -16,6 +16,9 @@
 
 package eu.teraflow.policy.model;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import eu.teraflow.policy.common.Util;
 import java.util.List;
 
@@ -25,7 +28,10 @@ public class PolicyRuleDevice {
     private final List<String> deviceIds;
 
     public PolicyRuleDevice(PolicyRuleBasic policyRuleBasic, List<String> deviceIds) {
+        checkNotNull(policyRuleBasic, "PolicyRuleBasic must not be null.");
         this.policyRuleBasic = policyRuleBasic;
+        checkNotNull(deviceIds, "Device Ids must not be null.");
+        checkArgument(!deviceIds.isEmpty(), "Device Ids must not be empty.");
         this.deviceIds = deviceIds;
     }
 
diff --git a/src/policy/src/test/java/eu/teraflow/policy/PolicyRuleBasicValidationTest.java b/src/policy/src/test/java/eu/teraflow/policy/PolicyRuleBasicValidationTest.java
index 907473f80..53cddf6be 100644
--- a/src/policy/src/test/java/eu/teraflow/policy/PolicyRuleBasicValidationTest.java
+++ b/src/policy/src/test/java/eu/teraflow/policy/PolicyRuleBasicValidationTest.java
@@ -56,7 +56,7 @@ class PolicyRuleBasicValidationTest {
     }
 
     private List<PolicyRuleCondition> createPolicyRuleConditions(
-            String kpiId, NumericalOperator numericalOperator, KpiValue kpiValue) {
+            String kpiId, NumericalOperator numericalOperator, KpiValue<?> kpiValue) {
         final var policyRuleCondition = new PolicyRuleCondition(kpiId, numericalOperator, kpiValue);
 
         return List.of(policyRuleCondition);
diff --git a/src/policy/src/test/java/eu/teraflow/policy/PolicyRuleDeviceValidationTest.java b/src/policy/src/test/java/eu/teraflow/policy/PolicyRuleDeviceValidationTest.java
new file mode 100644
index 000000000..064cd7ee0
--- /dev/null
+++ b/src/policy/src/test/java/eu/teraflow/policy/PolicyRuleDeviceValidationTest.java
@@ -0,0 +1,178 @@
+/*
+* Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+*
+* Licensed 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 eu.teraflow.policy;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+
+import eu.teraflow.policy.model.BooleanOperator;
+import eu.teraflow.policy.model.NumericalOperator;
+import eu.teraflow.policy.model.PolicyRuleAction;
+import eu.teraflow.policy.model.PolicyRuleActionEnum;
+import eu.teraflow.policy.model.PolicyRuleBasic;
+import eu.teraflow.policy.model.PolicyRuleCondition;
+import eu.teraflow.policy.model.PolicyRuleDevice;
+import eu.teraflow.policy.model.PolicyRuleState;
+import eu.teraflow.policy.model.RuleState;
+import eu.teraflow.policy.monitoring.model.IntegerKpiValue;
+import eu.teraflow.policy.monitoring.model.KpiValue;
+import io.quarkus.test.junit.QuarkusTest;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+class PolicyRuleDeviceValidationTest {
+
+    private PolicyRuleBasic createPolicyRuleBasic(
+            String policyRuleId,
+            int priority,
+            PolicyRuleState policyRuleState,
+            BooleanOperator booleanOperator,
+            List<PolicyRuleCondition> policyRuleConditions,
+            List<PolicyRuleAction> policyRuleActions) {
+
+        return new PolicyRuleBasic(
+                policyRuleId,
+                policyRuleState,
+                priority,
+                policyRuleConditions,
+                booleanOperator,
+                policyRuleActions);
+    }
+
+    private List<PolicyRuleCondition> createPolicyRuleConditions(
+            String kpiId, NumericalOperator numericalOperator, KpiValue<?> kpiValue) {
+        final var policyRuleCondition = new PolicyRuleCondition(kpiId, numericalOperator, kpiValue);
+
+        return List.of(policyRuleCondition);
+    }
+
+    private List<PolicyRuleAction> createPolicyRuleActions(
+            PolicyRuleActionEnum policyRuleActionEnum, List<String> parameters) {
+        final var policyRuleAction = new PolicyRuleAction(policyRuleActionEnum, parameters);
+
+        return List.of(policyRuleAction);
+    }
+
+    private PolicyRuleDevice createPolicyRuleDevice(
+            PolicyRuleBasic policyRuleBasic, List<String> deviceIds) {
+
+        return new PolicyRuleDevice(policyRuleBasic, deviceIds);
+    }
+
+    private List<String> createDeviceIds() {
+        return List.of("deviceId1", "deviceId2");
+    }
+
+    @Test
+    void shouldThrowNullPointerExceptionGivenNullPolicyRuleBasic() {
+        final var deviceIds = createDeviceIds();
+
+        assertThatExceptionOfType(NullPointerException.class)
+                .isThrownBy(() -> createPolicyRuleDevice(null, deviceIds));
+    }
+
+    @Test
+    void shouldThrowNullPointerExceptionGivenNullDeviceIds() {
+        final var policyRuleConditions =
+                createPolicyRuleConditions(
+                        UUID.randomUUID().toString(),
+                        NumericalOperator.POLICY_RULE_CONDITION_NUMERICAL_LESS_THAN,
+                        new IntegerKpiValue(3));
+        final var policyRuleActions =
+                createPolicyRuleActions(
+                        PolicyRuleActionEnum.POLICY_RULE_ACTION_ADD_SERVICE_CONSTRAINT,
+                        List.of(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
+
+        final var policyRuleState = new PolicyRuleState(RuleState.POLICY_EFFECTIVE);
+
+        final var policyRuleBasic =
+                createPolicyRuleBasic(
+                        "policyRuleId",
+                        3,
+                        policyRuleState,
+                        BooleanOperator.POLICYRULE_CONDITION_BOOLEAN_OR,
+                        policyRuleConditions,
+                        policyRuleActions);
+
+        assertThatExceptionOfType(NullPointerException.class)
+                .isThrownBy(() -> createPolicyRuleDevice(policyRuleBasic, null));
+    }
+
+    @Test
+    void shouldThrowIllegalArgumentExceptionGivenEmptyDeviceIds() {
+        final var policyRuleConditions =
+                createPolicyRuleConditions(
+                        UUID.randomUUID().toString(),
+                        NumericalOperator.POLICY_RULE_CONDITION_NUMERICAL_GREATER_THAN_EQUAL,
+                        new IntegerKpiValue(3));
+        final var policyRuleActions =
+                createPolicyRuleActions(
+                        PolicyRuleActionEnum.POLICY_RULE_ACTION_ADD_SERVICE_CONFIGRULE,
+                        List.of(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
+
+        final var policyRuleState = new PolicyRuleState(RuleState.POLICY_EFFECTIVE);
+
+        final var policyRuleBasic =
+                createPolicyRuleBasic(
+                        "policyRuleId1",
+                        213,
+                        policyRuleState,
+                        BooleanOperator.POLICYRULE_CONDITION_BOOLEAN_AND,
+                        policyRuleConditions,
+                        policyRuleActions);
+
+        final var deviceIds = Collections.<String>emptyList();
+
+        assertThatExceptionOfType(IllegalArgumentException.class)
+                .isThrownBy(() -> createPolicyRuleDevice(policyRuleBasic, deviceIds));
+    }
+
+    @Test
+    void shouldCreatePolicyRuleDeviceObject() {
+        final var policyRuleConditions =
+                createPolicyRuleConditions(
+                        UUID.randomUUID().toString(),
+                        NumericalOperator.POLICY_RULE_CONDITION_NUMERICAL_NOT_EQUAL,
+                        new IntegerKpiValue(3));
+        final var policyRuleActions =
+                createPolicyRuleActions(
+                        PolicyRuleActionEnum.POLICY_RULE_ACTION_SET_DEVICE_STATUS,
+                        List.of(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
+
+        final var policyRuleState = new PolicyRuleState(RuleState.POLICY_EFFECTIVE);
+
+        final var policyRuleBasic =
+                createPolicyRuleBasic(
+                        "policyRuleId",
+                        3,
+                        policyRuleState,
+                        BooleanOperator.POLICYRULE_CONDITION_BOOLEAN_OR,
+                        policyRuleConditions,
+                        policyRuleActions);
+
+        final var deviceIds = createDeviceIds();
+
+        final var expectedPolicyRuleDevice = new PolicyRuleDevice(policyRuleBasic, deviceIds);
+
+        final var policyRuleDevice = createPolicyRuleDevice(policyRuleBasic, deviceIds);
+
+        assertThat(policyRuleDevice).usingRecursiveComparison().isEqualTo(expectedPolicyRuleDevice);
+    }
+}
diff --git a/src/policy/src/test/java/eu/teraflow/policy/PolicyServiceTest.java b/src/policy/src/test/java/eu/teraflow/policy/PolicyServiceTest.java
index 7e3044c1d..3f1232432 100644
--- a/src/policy/src/test/java/eu/teraflow/policy/PolicyServiceTest.java
+++ b/src/policy/src/test/java/eu/teraflow/policy/PolicyServiceTest.java
@@ -144,11 +144,26 @@ class PolicyServiceTest {
     void shouldAddPolicyDevice() throws ExecutionException, InterruptedException, TimeoutException {
         CompletableFuture<String> message = new CompletableFuture<>();
 
+        final var expectedDeviceIdUuid1 =
+                serializer.serializeUuid("20db867c-772d-4872-9179-244ecafb3257");
+        final var expectedDeviceIdUuid2 =
+                serializer.serializeUuid("095974ac-d757-412d-b317-bcf355220aa9");
+
+        final var expectedDeviceId1 =
+                ContextOuterClass.DeviceId.newBuilder().setDeviceUuid(expectedDeviceIdUuid1).build();
+        final var expectedDeviceId2 =
+                ContextOuterClass.DeviceId.newBuilder().setDeviceUuid(expectedDeviceIdUuid2).build();
+
         final var policyRuleBasic = createPolicyRuleBasic();
+        final var deviceIds = List.of(expectedDeviceId1, expectedDeviceId2);
+
         final var expectedPolicyRuleState = policyRuleBasic.getPolicyRuleState();
 
         final var policyRuleDevice =
-                Policy.PolicyRuleDevice.newBuilder().setPolicyRuleBasic(policyRuleBasic).build();
+                Policy.PolicyRuleDevice.newBuilder()
+                        .setPolicyRuleBasic(policyRuleBasic)
+                        .addAllDeviceList(deviceIds)
+                        .build();
 
         client
                 .policyAddDevice(policyRuleDevice)
diff --git a/src/policy/target/kubernetes/kubernetes.yml b/src/policy/target/kubernetes/kubernetes.yml
index 360485dcc..680929bc0 100644
--- a/src/policy/target/kubernetes/kubernetes.yml
+++ b/src/policy/target/kubernetes/kubernetes.yml
@@ -3,20 +3,20 @@ apiVersion: v1
 kind: Service
 metadata:
   annotations:
-    app.quarkus.io/commit-id: a5550cfa37e56aef1054126dd063b112df66b531
-    app.quarkus.io/build-timestamp: 2022-08-04 - 21:21:19 +0000
+    app.quarkus.io/commit-id: 7d24cfdf286fcca1ff04620ee026933bedd8960e
+    app.quarkus.io/build-timestamp: 2022-08-04 - 22:13:18 +0000
   labels:
     app.kubernetes.io/name: policyservice
     app: policyservice
   name: policyservice
 spec:
   ports:
-    - name: grpc
-      port: 6060
-      targetPort: 6060
     - name: http
       port: 8080
       targetPort: 8080
+    - name: grpc
+      port: 6060
+      targetPort: 6060
   selector:
     app.kubernetes.io/name: policyservice
   type: ClusterIP
@@ -25,8 +25,8 @@ apiVersion: apps/v1
 kind: Deployment
 metadata:
   annotations:
-    app.quarkus.io/commit-id: a5550cfa37e56aef1054126dd063b112df66b531
-    app.quarkus.io/build-timestamp: 2022-08-04 - 21:21:19 +0000
+    app.quarkus.io/commit-id: 7d24cfdf286fcca1ff04620ee026933bedd8960e
+    app.quarkus.io/build-timestamp: 2022-08-04 - 22:13:18 +0000
   labels:
     app: policyservice
     app.kubernetes.io/name: policyservice
@@ -39,8 +39,8 @@ spec:
   template:
     metadata:
       annotations:
-        app.quarkus.io/commit-id: a5550cfa37e56aef1054126dd063b112df66b531
-        app.quarkus.io/build-timestamp: 2022-08-04 - 21:21:19 +0000
+        app.quarkus.io/commit-id: 7d24cfdf286fcca1ff04620ee026933bedd8960e
+        app.quarkus.io/build-timestamp: 2022-08-04 - 22:13:18 +0000
       labels:
         app: policyservice
         app.kubernetes.io/name: policyservice
@@ -51,10 +51,10 @@ spec:
               valueFrom:
                 fieldRef:
                   fieldPath: metadata.namespace
-            - name: SERVICE_SERVICE_HOST
-              value: serviceservice
             - name: CONTEXT_SERVICE_HOST
               value: contextservice
+            - name: SERVICE_SERVICE_HOST
+              value: serviceservice
             - name: MONITORING_SERVICE_HOST
               value: monitoringservice
           image: registry.gitlab.com/teraflow-h2020/controller/policy:0.1.0
@@ -71,12 +71,12 @@ spec:
             timeoutSeconds: 10
           name: policyservice
           ports:
-            - containerPort: 6060
-              name: grpc
-              protocol: TCP
             - containerPort: 8080
               name: http
               protocol: TCP
+            - containerPort: 6060
+              name: grpc
+              protocol: TCP
           readinessProbe:
             failureThreshold: 3
             httpGet:
-- 
GitLab