package com.thinkbiganalytics.metadata.core.sla.feed; /*- * #%L * thinkbig-metadata-core * %% * Copyright (C) 2017 ThinkBig Analytics * %% * 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. * #L% */ import com.thinkbiganalytics.metadata.api.feed.Feed; import com.thinkbiganalytics.metadata.api.feed.FeedCriteria; import com.thinkbiganalytics.metadata.api.feed.FeedProvider; import com.thinkbiganalytics.metadata.api.op.FeedOperation; import com.thinkbiganalytics.metadata.api.op.FeedOperationsProvider; import com.thinkbiganalytics.metadata.api.sla.FeedExecutedSinceFeed; import com.thinkbiganalytics.metadata.sla.api.AssessmentResult; import com.thinkbiganalytics.metadata.sla.api.Metric; import com.thinkbiganalytics.metadata.sla.api.MetricAssessment; import com.thinkbiganalytics.metadata.sla.spi.MetricAssessmentBuilder; import org.joda.time.DateTime; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import java.io.Serializable; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class FeedExecutedSinceFeedAssessorTest { private FeedExecutedSinceFeed metric; private TestMetricAssessmentBuilder builder; @Before public void setUp() { metric = new FeedExecutedSinceFeed("mainCategory.mainFeed", "triggeredCategory.triggeredFeed"); builder = new TestMetricAssessmentBuilder(); } /** * Use case: <br> * - feed b depends on a <br> * - feed a1 completes */ @Test public void testTriggeredNeverRan() throws Exception { int triggeredFeedStartTime = -1; boolean isTriggeredFeedRunning = false; int mainFeedStopTime = 1; boolean isMainFeedRunning = false; assertResult(AssessmentResult.SUCCESS, triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); } /** * Use case: <br> * - feed c depends on both a and b <br> * - feed c never ran <br> * - feed b never ran <br> * - feed a completes <br> * - assessment for both feed "a" and "b" will be done on feed "a" completion <br> * - this is the assessment scenario for feed b <br> */ @Test public void testMainNeverRan() throws Exception { int triggeredFeedStartTime = 1; boolean isTriggeredFeedRunning = false; int mainFeedStopTime = -1; boolean isMainFeedRunning = false; assertResult(AssessmentResult.FAILURE, triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); } /** * Use case: <br> * - feed a1 triggers feed b1 and feed b1 completes <br> * - feed a2 completes <br> */ @Test public void testTriggeredStartedBeforeMainStopped() throws Exception { int triggeredFeedStartTime = 1; boolean isTriggeredFeedRunning = false; int mainFeedStopTime = 2; boolean isMainFeedRunning = false; assertResult(AssessmentResult.SUCCESS, triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); } /** * Use case: <br> * - feed c depends on both a and b <br> * - feed a completes <br> * - feed b completes <br> * - feed c is triggered and completes <br> * - feed a completes <br> * - this is the case for feed b assessment on feed a's completion <br> */ @Test public void testTriggeredStartedAfterMainStopped() throws Exception { int triggeredFeedStartTime = 2; boolean isTriggeredFeedRunning = false; int mainFeedStopTime = 1; boolean isMainFeedRunning = false; assertResult(AssessmentResult.FAILURE, triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); } /** * Use case: <br> * - feed c depends on a and b <br> * - feed a1 completes <br> * - feed b1 completes <br> * - feed c1 is triggered and completes <br> * - feed a2 is started and is still running <br> * - feed b2 completes <br> * - feed b2 is started and is still running <br> * - feed a2 completes <br> * - we are now assessing feed b - c feed would have started before feed b stopped and feed b is still running <br> */ @Test public void testTriggeredStartedBeforeMainStoppedAndMainIsRunning() throws Exception { int triggeredFeedStartTime = 1; boolean isTriggeredFeedRunning = false; int mainFeedStopTime = 2; boolean isMainFeedRunning = true; assertResult(AssessmentResult.SUCCESS, triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); } /** * Use Case: <br> * - feed c depends on both a and b <br> * - feed a1 completes <br> * - feed b1 completes <br> * - feed c1 triggered <br> * - feed a2 started and is still running <br> * - feed b2 completes <br> * - we are now assessing feed a <br> */ @Test public void testTriggeredStartedAfterMainStoppedAndMainIsRunning() throws Exception { int triggeredFeedStartTime = 2; boolean isTriggeredFeedRunning = false; int mainFeedStopTime = 1; boolean isMainFeedRunning = true; assertResult(AssessmentResult.FAILURE, triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); } /** * Use Case; <br> * - feed a1 triggered feed b1 and b1 completes <br> * - feed a2 triggered feed b2 and b2 is still running <br> * - feed a3 triggered feed b3 <br> */ @Test public void testTriggeredStartedBeforeMainStoppedAndTriggeredIsRunning() throws Exception { int triggeredFeedStartTime = 1; boolean isTriggeredFeedRunning = true; int mainFeedStopTime = 2; boolean isMainFeedRunning = false; assertResult(AssessmentResult.SUCCESS, triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); } /** * Use Case: <br> * - feed c depends on both a and b <br> * - feed a1 completes <br> * - feed b1 completes <br> * - feed c1 is triggered and is still running <br> * - feed b2 completes and c1 is still running <br> * - we are now assessing a's preconditions <br> */ @Test public void testTriggeredStartedAfterMainStoppedAndTriggeredIsRunning() throws Exception { int triggeredFeedStartTime = 2; boolean isTriggeredFeedRunning = true; int mainFeedStopTime = 1; boolean isMainFeedRunning = false; assertResult(AssessmentResult.FAILURE, triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); } /** * Use Case: <br> * - feed a1 triggers feed b1 and b1 is still running <br> * - feed a2 starts and is still running <br> * - feed a3 completes <br> */ @Test public void testTriggeredStartedBeforeMainStoppedAndBothTriggeredAndMainAreRunning() throws Exception { int triggeredFeedStartTime = 1; boolean isTriggeredFeedRunning = true; int mainFeedStopTime = 2; boolean isMainFeedRunning = true; assertResult(AssessmentResult.SUCCESS, triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); } /** * Use Case: <br> * - its possible! <br> * - feed c depends on both a and b <br> * - feed a1 completes, feed b1 completes, triggered feed c1 completes <br> * - feed a2 starts and is running <br> * - feed a3 completes, feed b2 completes, triggered feed c2 started and is still running <br> * - feed b3 completes <br> * - we are now assessing feed a where feed a2 is still running and c2 is still running and c2 started after last a3 <br> */ @Test public void testTriggeredStartedAfterMainStoppedAndBothTriggeredAndMainAreRunning() throws Exception { int triggeredFeedStartTime = 2; boolean isTriggeredFeedRunning = true; int mainFeedStopTime = 1; boolean isMainFeedRunning = true; assertResult(AssessmentResult.FAILURE, triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); } private void assertResult(AssessmentResult expected, int triggeredFeedStartTime, boolean isTriggeredFeedRunning, int mainFeedStopTime, boolean isMainFeedRunning) { FeedExecutedSinceFeedAssessor assessor = setUpAssessor(triggeredFeedStartTime, isTriggeredFeedRunning, mainFeedStopTime, isMainFeedRunning); assessor.assess(metric, builder); Assert.assertEquals(expected, builder.getResult()); } /** * @param triggeredFeedStartTime pass negative value for empty operations list * @param mainFeedStopTime pass negative for empty operations list */ private FeedExecutedSinceFeedAssessor setUpAssessor(int triggeredFeedStartTime, boolean isTriggeredFeedRunning, int mainFeedStopTime, boolean isMainFeedRunning) { FeedCriteria dummyCriteria = mock(FeedCriteria.class); when(dummyCriteria.name(Mockito.anyString())).thenReturn(dummyCriteria); when(dummyCriteria.category(Mockito.anyString())).thenReturn(dummyCriteria); FeedProvider feedProvider = mock(FeedProvider.class); when(feedProvider.feedCriteria()).thenReturn(dummyCriteria); List<Feed> triggeredFeeds = new ArrayList<>(); Feed triggeredFeed = mock(Feed.class); Feed.ID triggeredFeedId = mock(Feed.ID.class); when(triggeredFeed.getId()).thenReturn(triggeredFeedId); triggeredFeeds.add(triggeredFeed); List<Feed> mainFeeds = new ArrayList<>(); Feed mainFeed = mock(Feed.class); Feed.ID mainFeedId = mock(Feed.ID.class); when(mainFeed.getId()).thenReturn(mainFeedId); mainFeeds.add(mainFeed); when(feedProvider.getFeeds(dummyCriteria)).thenReturn(mainFeeds, triggeredFeeds); FeedOperationsProvider opsProvider = mock(FeedOperationsProvider.class); List<FeedOperation> triggeredFeedOps = new ArrayList<>(); if (triggeredFeedStartTime > 0) { FeedOperation triggeredOp = mock(FeedOperation.class); when(triggeredOp.getStartTime()).thenReturn(new DateTime(triggeredFeedStartTime)); triggeredFeedOps.add(triggeredOp); } List<FeedOperation> mainFeedOps = new ArrayList<>(); if (mainFeedStopTime > 0) { FeedOperation mainFeedOp = mock(FeedOperation.class); when(mainFeedOp.getStopTime()).thenReturn(new DateTime(mainFeedStopTime)); mainFeedOps.add(mainFeedOp); } when(opsProvider.findLatestCompleted(mainFeedId)).thenReturn(mainFeedOps); when(opsProvider.findLatest(triggeredFeedId)).thenReturn(triggeredFeedOps); when(opsProvider.isFeedRunning(mainFeedId)).thenReturn(isMainFeedRunning); when(opsProvider.isFeedRunning(triggeredFeedId)).thenReturn(isTriggeredFeedRunning); return new FeedExecutedSinceFeedAssessor() { @Override protected FeedProvider getFeedProvider() { return feedProvider; } @Override protected FeedOperationsProvider getFeedOperationsProvider() { return opsProvider; } }; } class TestMetricAssessmentBuilder implements MetricAssessmentBuilder<Serializable> { AssessmentResult result; String message; Metric metric; public AssessmentResult getResult() { return result; } public String getMessage() { return message; } public Metric getMetric() { return metric; } @Override public MetricAssessmentBuilder<Serializable> metric(Metric metric) { this.metric = metric; return this; } @Override public MetricAssessmentBuilder<Serializable> message(String descr) { this.message = descr; return this; } @Override public MetricAssessmentBuilder<Serializable> comparitor(Comparator<MetricAssessment<Serializable>> comp) { throw new UnsupportedOperationException(); } @Override public MetricAssessmentBuilder<Serializable> compareWith(Comparable<? extends Serializable> value, Comparable<? extends Serializable>[] otherValues) { throw new UnsupportedOperationException(); } @Override public MetricAssessmentBuilder<Serializable> data(Serializable data) { throw new UnsupportedOperationException(); } @Override public MetricAssessmentBuilder<Serializable> result(AssessmentResult result) { this.result = result; return this; } } }