Commit 73716e49 authored by Kostis Trantzas's avatar Kostis Trantzas
Browse files

Merge branch '10-increase-metrico-test-coverage' into 'develop'

Resolve "Increase METRICO test coverage"

See merge request !11
parents 0d0c0a76 0741e890
Loading
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -232,6 +232,12 @@
			<version>1.2.0-SNAPSHOT</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-test-spring-junit5</artifactId>
			<version>3.20.2</version> <!-- Use the version matching your Camel version -->
			<scope>test</scope>
		</dependency>

	</dependencies>

+0 −53
Original line number Diff line number Diff line
package org.etsi.osl.metrico;

import org.apache.camel.builder.RouteBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Profile("testing")
@Component
public class DummyRouteBuilder extends RouteBuilder {
    private static final Logger logger = LoggerFactory.getLogger(DummyRouteBuilder.class);

    @Value("${PM_MEASUREMENT_COLLECTION_JOB_UPDATE}")
    private String PM_MEASUREMENT_COLLECTION_JOB_UPDATE = "";
    @Value("${PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID}")
    private String PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID = "";
    @Value("${PM_MEASUREMENT_COLLECTION_JOBS_GET}")
    private String PM_MEASUREMENT_COLLECTION_JOBS_GET = "";
    @Value("${CATALOG_GET_SERVICE_BY_ID}")
    private String CATALOG_GET_SERVICE_BY_ID = ""; 
    @Value("${CATALOG_UPD_SERVICE}")
    private String CATALOG_UPD_SERVICE = "";
    @Value("${CATALOG_GET_RESOURCE_BY_ID}")
    private String CATALOG_GET_RESOURCE_BY_ID = "";
    @Value("${CATALOG_UPD_RESOURCE}")
    private String CATALOG_UPD_RESOURCE = "";
    @Value("${CATALOG_UPDADD_RESOURCESPEC}")
    private String CATALOG_UPDADD_RESOURCESPEC = "";

    private final String measurementCollectionJobJson = "{\n" +
            "  \"outputFormat\": \"JSON\",\n" +
            "  \"@type\": \"MeasurementCollectionJob\",\n" +
            "  \"consumingApplicationId\": \"app123\",\n" +
            "  \"producingApplicationId\": \"app456\",\n" +
            "  \"dataAccessEndpoint\": [],\n" +
            "  \"jobPriority\": 1,\n" +
            "  \"lastModifiedTime\": \"2023-01-01T00:00:00Z\",\n" +
            "  \"scheduleDefinition\": []\n" +
            "}";

    @Override
    public void configure() throws Exception {
        logger.info("Configuring dummy routes...");

        from("direct:PM.MEASUREMENTCOLLECTIONJOB.GET_BY_ID")
                .process(exchange -> {
                    logger.info("Processing GET_BY_ID route");
                    exchange.getIn().setBody(measurementCollectionJobJson);
                });
    }
}
 No newline at end of file
+10 −0
Original line number Diff line number Diff line
@@ -44,4 +44,14 @@ class JsonUtilTest {
        assertNull(jsonString);
    }

    @Test
    void toJsonString_unserializableObject_returnsNull() {
        class SelfRef {
            public SelfRef ref;
        }
        SelfRef obj = new SelfRef();
        obj.ref = obj; // creates a circular reference
        String jsonString = JsonUtil.toJsonString(obj);
        assertNull(jsonString);
    }
}
 No newline at end of file
+323 −0
Original line number Diff line number Diff line
package org.etsi.osl.metrico;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.etsi.osl.tmf.common.model.ELifecycle;
import org.etsi.osl.tmf.common.model.EValueType;
import org.etsi.osl.tmf.pm628.model.*;
import org.etsi.osl.tmf.rcm634.model.LogicalResourceSpecification;
import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationCharacteristic;
import org.etsi.osl.tmf.ri639.model.LogicalResource;
import org.etsi.osl.tmf.ri639.model.ResourceUpdate;
import org.etsi.osl.tmf.sim638.model.Service;
import org.etsi.osl.tmf.sim638.model.ServiceUpdate;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;

import java.io.IOException;
import java.net.URI;
import java.time.OffsetDateTime;
import java.util.*;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest(properties = {
        "PM_MEASUREMENT_COLLECTION_JOB_UPDATE = direct:PM.MEASUREMENTCOLLECTIONJOB.UPDATE",
        "PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID = direct:PM.MEASUREMENTCOLLECTIONJOB.GET_BY_ID",
        "PM_MEASUREMENT_COLLECTION_JOBS_GET = direct:PM.MEASUREMENTCOLLECTIONJOBS.GET",
        "PM_MEASUREMENT_COLLECTION_JOB_GET_INPROGRESS_OR_PENDING = direct:PM.MEASUREMENTCOLLECTIONJOB.GET_INPROGRESS_OR_PENDING",
        "CATALOG_GET_SERVICE_BY_ID = direct:CATALOG.GET.SERVICE",
        "CATALOG_UPD_SERVICE = direct:CATALOG.UPD.SERVICE",
        "CATALOG_GET_RESOURCE_BY_ID = direct:CATALOG.GET.RESOURCE",
        "CATALOG_UPD_RESOURCE = direct:CATALOG.UPD.RESOURCE",
        "CATALOG_UPDADD_RESOURCESPEC = direct:CATALOG.UPDADD.RESOURCESPEC"
})
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MetricoCommonMethodsTest {

      static String OSL_METRICO_RSPEC_NAME = "Metrico_Resource_Specification";
      static String OSL_METRICO_RSPEC_CATEGORY = "metrico.osl.etsi.org/v1";
      static String OSL_METRICO_RSPEC_VERSION = "1.0.0";
      static String OSL_METRICO_RSPEC_DESCRIPTION = "This Specification is used to describe a generic METRICO job resource";
      static String OSL_METRICO_RSPEC_TYPE = "LogicalResourceSpecification";

    @TestConfiguration
    static class CamelTestRoutesConfig {
        private final CamelContext camelContext;

        public CamelTestRoutesConfig(CamelContext camelContext) {
            this.camelContext = camelContext;
        }

        @PostConstruct
        public void registerRoutes() throws Exception {
            camelContext.addRoutes(
                new RouteBuilder() {
                    @Override
                    public void configure() {
                        from("direct:PM.MEASUREMENTCOLLECTIONJOB.UPDATE").bean(MetricoCommonMethodsTest.class, "mockUpdateMeasurementCollectionJob(${header.mcjid}, ${body})");
                        from("direct:PM.MEASUREMENTCOLLECTIONJOB.GET_BY_ID").bean(MetricoCommonMethodsTest.class, "mockFindMeasurementCollectionJobByUuidEagerAsString");
                        from("direct:PM.MEASUREMENTCOLLECTIONJOBS.GET").bean(MetricoCommonMethodsTest.class, "mockFindAllMeasurementCollectionJobs");
                        from("direct:PM.MEASUREMENTCOLLECTIONJOB.GET_INPROGRESS_OR_PENDING").bean(MetricoCommonMethodsTest.class, "mockFindPendingOrInProgressMeasurementCollectionJobsAsJson");
                        from("direct:CATALOG.GET.SERVICE").bean(MetricoCommonMethodsTest.class, "mockGetServiceEagerAsString");
                        from("direct:CATALOG.UPD.SERVICE").bean(MetricoCommonMethodsTest.class, "mockUpdateService(${header.serviceid}, ${body}, ${header.triggerServiceActionQueue})");
                        from("direct:CATALOG.GET.RESOURCE").bean(MetricoCommonMethodsTest.class, "mockGetResourceEagerAsString");
                        from("direct:CATALOG.UPD.RESOURCE").bean(MetricoCommonMethodsTest.class, "mockUpdateResource(${header.resourceId}, ${body}, ${header.triggerServiceActionQueue})");
                        from("direct:CATALOG.UPDADD.RESOURCESPEC").bean(MetricoCommonMethodsTest.class, "mockAddOrUpdateResourceSpecificationByNameCategoryVersion()");
                    }
                }
            );
        }
    }

    @Autowired
    private ProducerTemplate template;
    @Autowired
    private MetricoCommonMethods methods;

    @Test
    void testRetrieveMeasurementCollectionJob() throws Exception {
        String jobId = "default-job-uuid";
        MeasurementCollectionJob result = methods.retrieveMeasurementCollectionJob(jobId);
        assertNotNull(result);
        assertEquals(jobId, result.getUuid());
    }

    @Test
    void testRetrieveMeasurementCollectionJobNull() throws Exception {
        String jobId = "not-in-db-job-uuid";
        MeasurementCollectionJob result = methods.retrieveMeasurementCollectionJob(jobId);
        assertNull(result);
    }

    @Test
    void testRetrieveMeasurementCollectionJobNFromMcjRef() throws Exception {
        MeasurementCollectionJobRef mcjRef = new MeasurementCollectionJobRef();
        mcjRef.setId("default-job-uuid");
        MeasurementCollectionJob result = methods.retrieveMeasurementCollectionJob(mcjRef);
        assertNotNull(result);
        assertEquals(mcjRef.getId(), result.getUuid());
    }

    @Test
    void testRetrieveMeasurementCollectionJobNFromMcjRefNull() throws Exception {
        MeasurementCollectionJobRef mcjRef = new MeasurementCollectionJobRef();
        mcjRef.setId("not-in-db-job-uuid");
        MeasurementCollectionJob result = methods.retrieveMeasurementCollectionJob(mcjRef);
        assertNull(result);
    }

    @Test
    void testListMeasurementCollectionJob(){
        List<MeasurementCollectionJob> jobs = methods.listMeasurementCollectionJob();
        assertNotNull(jobs);
        assertFalse(jobs.isEmpty());
        assertEquals(2, jobs.size()); // We mocked two jobs in the method
    }

    @Test
    void testListPendingOrInProgressMeasurementCollectionJobs() {
        List<MeasurementCollectionJob> jobs = methods.listPendingOrInProgressMeasurementCollectionJobs();
        assertNull(jobs);
    }

    @Test
    void testUpdateMeasurementCollectionJobById() {
        String jobId = "default-job-uuid";
        MeasurementCollectionJobMVO mcjMVO = new MeasurementCollectionJobMVO();
        mcjMVO.setUuid(jobId);

        mcjMVO.setGranularity(Granularity.G_1H);


        MeasurementCollectionJob result = methods.updateMeasurementCollectionJobById(jobId, mcjMVO);
        MeasurementCollectionJob updatedJob;

        assertNotNull(result);
        assertEquals(result.getUuid(), jobId);
        assertEquals(Granularity.G_1H, result.getGranularity());
    }

// Bellow here are the mocked methods for the test class
    public static String mockUpdateMeasurementCollectionJob(String uuid, String mcjMVOString) {
        MeasurementCollectionJob mcj = defaultMeasurementCollectionJob();

        MeasurementCollectionJobMVO mcjMVO = null;
        try {
            mcjMVO = JsonUtil.toJsonObj(mcjMVOString, MeasurementCollectionJobMVO.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        mcj.setGranularity(mcjMVO.getGranularity());

        return JsonUtil.toJsonString(mcj);
    }

    public static String mockFindMeasurementCollectionJobByUuidEagerAsString(String uuid) {
        if(uuid.equals("default-job-uuid")) {
            return JsonUtil.toJsonString(defaultMeasurementCollectionJob());
        }
        else return  null;
    }

    public static String mockFindAllMeasurementCollectionJobs() {
        MeasurementCollectionJob job1 = defaultMeasurementCollectionJob();
        MeasurementCollectionJob job2 = defaultMeasurementCollectionJob();
        job2.setUuid("another-job-uuid");
        List<MeasurementCollectionJob> jobs = List.of(job1, job2);

        try {
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonArray;

            List<String> jobJsonStrings = new ArrayList<>();
            for (MeasurementCollectionJob job : jobs) {
                jobJsonStrings.add(objectMapper.writeValueAsString(job));
            }
            StringJoiner joiner = new StringJoiner(",", "[", "]");
            for (String jobStr : jobJsonStrings) {
                joiner.add(jobStr);
            }
            jsonArray = joiner.toString();
            return jsonArray;
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to serialize jobs to JSON", e);
        }
    }

    public static String mockFindPendingOrInProgressMeasurementCollectionJobsAsJson() {
        return null;
    }

    public static String mockGetServiceEagerAsString(String serviceId) {
        try {
            Service service = new Service();
            service.setUuid("mock-service-id");
            service.setName("Mock Service");
            // Set other fields as needed for your tests

            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(service);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String mockUpdateService(String serviceId, ServiceUpdate body, Boolean triggerServiceActionQueue) {
        try {
            Service service = new Service();
            service.setUuid("mock-service-id");
            service.setName("Updated Mock Service");
            // Optionally, set more fields based on the ServiceUpdate body if needed

            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(service);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String mockGetResourceEagerAsString(String resourceId) {
        try {
            LogicalResource resource = new LogicalResource();
            resource.setUuid("mock-service-id");
            resource.setName("Mock Resource");
            // Set other fields as needed for your tests

            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(resource);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String mockUpdateResource(String resourceId, ResourceUpdate body, Boolean triggerServiceActionQueue) {
        try {
            LogicalResource resource = new LogicalResource();
            resource.setUuid("mock-service-id");
            resource.setName("Updated Mock Resource");
            // Optionally, set more fields based on the ResourceUpdate body if needed

            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(resource);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String mockAddOrUpdateResourceSpecificationByNameCategoryVersion() {
       return JsonUtil.toJsonString(defaultResourceSpecification());
    }


    public static LogicalResourceSpecification defaultResourceSpecification() {
        LogicalResourceSpecification rsc = new LogicalResourceSpecification();
        rsc.setName(OSL_METRICO_RSPEC_NAME);
        rsc.setCategory(OSL_METRICO_RSPEC_CATEGORY);
        rsc.setVersion(OSL_METRICO_RSPEC_VERSION);
        rsc.setDescription(OSL_METRICO_RSPEC_DESCRIPTION);
        rsc.setType(OSL_METRICO_RSPEC_TYPE);
        rsc.setLifecycleStatus(ELifecycle.ACTIVE.getValue());

        ResourceSpecificationCharacteristic characteristic = new ResourceSpecificationCharacteristic();
        characteristic.setValueType(EValueType.TEXT.getValue());

        characteristic.setName("_MT_CHARACTERISTIC_NAME");
        rsc.addResourceSpecCharacteristicItem(characteristic);

        characteristic.setName("_MT_SERVICEUUID");
        rsc.addResourceSpecCharacteristicItem(characteristic);

        characteristic.setName("_MT_END_TIME");
        rsc.addResourceSpecCharacteristicItem(characteristic);

        characteristic.setName("_MT_START_TIME");
        rsc.addResourceSpecCharacteristicItem(characteristic);

        characteristic.setName("_MT_QUERY");
        rsc.addResourceSpecCharacteristicItem(characteristic);

        characteristic.setName("_MT_URL");
        rsc.addResourceSpecCharacteristicItem(characteristic);

        characteristic.setName("_MT_RECURRING_INTERVAL");
        rsc.addResourceSpecCharacteristicItem(characteristic);

        characteristic.setName("_MT_TYPE");
        rsc.addResourceSpecCharacteristicItem(characteristic);

        return rsc;
    }

    static MeasurementCollectionJob defaultMeasurementCollectionJob() {
        MeasurementCollectionJob job = new MeasurementCollectionJob();
        job.setCreationTime(OffsetDateTime.now());
        job.setUuid("default-job-uuid");
        job.setGranularity(Granularity.G_1MN);
        job.setExecutionState(ExecutionStateType.PENDING);

        DataAccessEndpoint dae = new DataAccessEndpoint();
        dae.setUri(URI.create("http://example.com/data"));
        dae.apiType("PROMETHEUS");
        List<DataAccessEndpoint> daeList = new ArrayList<>();
        daeList.add(dae);
        job.setDataAccessEndpoint(daeList);

        ScheduleDefinition sd = new ScheduleDefinition();
        sd.setScheduleDefinitionStartTime(OffsetDateTime.now());
        sd.setScheduleDefinitionEndTime(OffsetDateTime.now().plusHours(1));
        List<ScheduleDefinition> sdList = new ArrayList<>();
        sdList.add(sd);

        return job;
    }

}
 No newline at end of file
+28 −0
Original line number Diff line number Diff line
@@ -7,10 +7,14 @@ import org.etsi.osl.tmf.pm628.model.ExecutionStateType;
import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.time.OffsetDateTime;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@@ -121,4 +125,28 @@ class PrometheusQueriesTest {
        verify(metricoCommonMethods).updateService(eq("service-uuid"), any(), eq(true));
    }

    @Test
    void testStartPeriodicQuery_SchedulesStopJobWhenEndDateTimePresent() {
        Job job = new Job();
        job.setExecutionInterval(100);
        job.setEndDateTime(OffsetDateTime.now().plusSeconds(61));
        MeasurementCollectionJob mcj = new MeasurementCollectionJob();

        ScheduledExecutorService scheduler = mock(ScheduledExecutorService.class);

        try (MockedStatic<JobService> jobServiceStatic = mockStatic(JobService.class)) {
            jobServiceStatic.when(JobService::getScheduler).thenReturn(scheduler);

            when(jobService.startJob(any(Runnable.class), any(Job.class))).thenAnswer(invocation -> {
                Job j = invocation.getArgument(1);
                j.setState(ExecutionStateType.INPROGRESS);
                return j;
            });

            prometheusQueries.startPeriodicQuery("http://localhost:9090", "query=up", job, mcj);

            verify(scheduler).schedule(any(Runnable.class), eq(60L), eq(TimeUnit.SECONDS));
        }
    }

}
 No newline at end of file
Loading