package com.griddynamics.jagger.test.jaas.listener; import com.griddynamics.jagger.engine.e1.Provider; import com.griddynamics.jagger.engine.e1.collector.loadscenario.LoadScenarioInfo; import com.griddynamics.jagger.engine.e1.collector.loadscenario.LoadScenarioListener; import com.griddynamics.jagger.engine.e1.services.ServicesAware; import com.griddynamics.jagger.engine.e1.services.data.service.MetricEntity; import com.griddynamics.jagger.engine.e1.services.data.service.SessionEntity; import com.griddynamics.jagger.engine.e1.services.data.service.TestEntity; import com.griddynamics.jagger.invoker.InvocationException; import com.griddynamics.jagger.invoker.v2.DefaultHttpInvoker; import com.griddynamics.jagger.invoker.v2.JHttpEndpoint; import com.griddynamics.jagger.invoker.v2.JHttpQuery; import com.griddynamics.jagger.test.jaas.util.TestContext; import com.griddynamics.jagger.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.*; import java.util.stream.Collectors; /** * Loads expected data into temp storage({@link TestContext}). * <p> * Created by ELozovan on 2016-09-27. */ public class LoadScenarioConfigListener extends ServicesAware implements Provider<LoadScenarioListener> { private static final Logger LOGGER = LoggerFactory.getLogger(LoadScenarioConfigListener.class); @Override public LoadScenarioListener provide() { return new LoadScenarioListener() { @Override public void onStart(LoadScenarioInfo loadScenarioInfo) { super.onStart(loadScenarioInfo); //collect all test sessions Set<SessionEntity> sessionsAvailable = getDataService().getSessions(Collections.emptyList()); sessionsAvailable.forEach(this::correctDateFieldValue); TestContext.setSessions(sessionsAvailable); // collect sessions with not empty tests Map<SessionEntity, Set<TestEntity>> testToTest = sessionsAvailable.stream() .map(s-> Pair.of(s, getDataService().getTests(s))) .filter(e->!e.getSecond().isEmpty()) .collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)); Pair<SessionEntity, Map.Entry<TestEntity, Set<MetricEntity>>> testData = searchTestData(testToTest); Set<MetricEntity> metrics = testData.getSecond().getValue(); SessionEntity session = testData.getFirst(); metrics.forEach(this::correctDateFieldValue); TestContext.addMetrics(session.getId(), testData.getSecond().getKey().getName(), metrics); Set<TestEntity> tests = testToTest.get(session); tests.forEach(this::correctDateFieldValue); TestContext.addTests(session.getId(), tests); } @Override public void onStop(LoadScenarioInfo loadScenarioInfo) { super.onStop(loadScenarioInfo); DefaultHttpInvoker invoker = new DefaultHttpInvoker(); JHttpEndpoint jaasEndpoint = new JHttpEndpoint(TestContext.getEndpointUri()); // Request to delete executions not deleted during test run. for (Long executionId : TestContext.getCreatedExecutionIds()) { try { invoker.invoke(new JHttpQuery<String>().delete().path(TestContext.getExecutionsUri() + "/" + executionId), jaasEndpoint); } catch (InvocationException ignored) { } } } /** * Search and return random test with not empty plot data and summary for metrics */ private Pair<SessionEntity, Map.Entry<TestEntity, Set<MetricEntity>>> searchTestData(Map<SessionEntity, Set<TestEntity>> sessionsToTests){ Random rnd = new Random(); Pair<SessionEntity, Map.Entry<TestEntity, Set<MetricEntity>>> testData = null; for (Map.Entry<SessionEntity, Set<TestEntity>> sessionToTests : sessionsToTests.entrySet()) { Map<TestEntity, Set<MetricEntity>> testsToMetrics = getDataService().getMetricsByTests(sessionToTests.getValue()); for (Map.Entry<TestEntity, Set<MetricEntity>> testToMetrics : testsToMetrics.entrySet()) { if(testToMetrics.getValue().stream().anyMatch(m -> m.isPlotAvailable() && m.isSummaryAvailable())){ TestContext.setMetricPlotData(getDataService().getMetricPlotData(testToMetrics.getValue())); TestContext.setMetricSummaries(getDataService().getMetricSummary(testToMetrics.getValue())); testData = Pair.of(sessionToTests.getKey(), testToMetrics); if(rnd.nextFloat()>0.7){ //provide some randomization of test data between test runs return testData; } } } } if(testData==null){ throw new RuntimeException("There are no appropriate test data. Expected at least one test session with test has both metric plot data and summary"); } return testData; } /** * DataService returns dates as Timestamp, JSON deserialiser returns them as Date, so #equals() returns false anyway. * This crutch resets date fields values to avoid that type mismatch. */ private <T> void correctDateFieldValue(T entity) { final String getterPrefix = "get"; Method[] allMethods = entity.getClass().getDeclaredMethods(); for (Method m : allMethods) { String mName = m.getName(); Type mReturnType = m.getGenericReturnType(); // Looking for a Date getXYZ() if (!(mName.startsWith(getterPrefix) && (mReturnType.equals(Date.class)))) { continue; } m.setAccessible(true); try { Date adjustedValue = new Date(((Date) m.invoke(entity)).getTime()); Method theSetter = entity.getClass().getDeclaredMethod(mName.replace(getterPrefix, "set"), Date.class); theSetter.setAccessible(true); theSetter.invoke(entity, adjustedValue); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { LOGGER.warn("Was not able to correct date value({}) in the entity {}.", mName, entity); } } } }; } }