/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.evaluate; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import static org.hamcrest.Matchers.*; import org.junit.After; import org.junit.AfterClass; import static org.junit.Assert.*; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.ArgumentCaptor; import static org.mockito.Mockito.*; import uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.PolicyRule; import uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.PolicyRules; import static uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.metric.MetricName.*; import static uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.metric.MetricValue.*; import static uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.operator.Operator.*; import static uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.scale.constraint.ScaleConstraint.*; import static uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.scale.factor.ScaleFactor.*; import static uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.threshold.MetricThreshold.*; import static uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.threshold.TimeThreshold.*; import uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.util.InfrastructureAdaptor; import uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.util.MetricReading; import uk.ac.imperial.lsds.seep.infrastructure.monitor.policy.util.MetricReadingProvider; /** * * @author mrouaux */ public class PolicyRulesEvaluatorTest { private InfrastructureAdaptor mockAdaptor = mock(InfrastructureAdaptor.class); private MetricReadingProvider mockProvider = mock(MetricReadingProvider.class); public PolicyRulesEvaluatorTest() { } @BeforeClass public static void setUpClass() { } @AfterClass public static void tearDownClass() { } @Before public void setUp() { } @After public void tearDown() { } private List<PolicyRule> evaluatorsToRules(List<PolicyRuleEvaluator> evaluators) { List<PolicyRule> rules = new ArrayList<PolicyRule>(); for(PolicyRuleEvaluator evaluator : evaluators) { rules.add(evaluator.getEvalSubject()); } return rules; } @Test public void testAllNullNoExceptionThrown() { System.out.println("testAllNullNoExceptionThrown"); try { PolicyRulesEvaluator evaluator = new PolicyRulesEvaluator(null, null); evaluator.evaluate(null); } catch(Exception e) { fail("No excetion should be thrown by PolicyRulesEvaluator"); } } @Test public void testEvaluateNoRulesWithoutWildcard() { System.out.println("testEvaluateNoRulesWithoutWildcard"); InfrastructureAdaptor mockAdaptor = mock(InfrastructureAdaptor.class); MetricReadingProvider mockProvider = mock(MetricReadingProvider.class); PolicyRules fakeRules = new PolicyRules() {}; try { PolicyRulesEvaluator evaluator = new PolicyRulesEvaluator(fakeRules, mockAdaptor); evaluator.evaluate(mockProvider); } catch(Exception e) { fail("No excetion should be thrown by PolicyRulesEvaluator"); } } @Test public void testEvaluateNoRulesWithSingleWildcard() { System.out.println("testEvaluateNoRulesWithWildcard"); final int operatorId = 1; MetricReading fakeReading = new MetricReading(); when(mockProvider.getOperatorId()).thenReturn(operatorId); when(mockProvider.nextReading()).thenReturn(fakeReading); PolicyRules fakeRules = new PolicyRules() {{ rule("CPU above 60% for 30 seconds") .scaleOut(allOperators()) .by(relative(2)).butNeverAbove(nodes(10)) .when(metric("cpu")) .is(above(percent(60))) .forAtLeast(seconds(30)).build(); }}; PolicyRulesEvaluator evaluator = spy(new PolicyRulesEvaluator(fakeRules, mockAdaptor)); ArgumentCaptor<PolicyRuleEvaluator> captorEvaluator = ArgumentCaptor.forClass(PolicyRuleEvaluator.class); doNothing().when(evaluator) .routeReadingToEvaluator(captorEvaluator.capture(), eq(mockProvider)); evaluator.evaluate(mockProvider); // Assertions, make sure that routing method is invoked on object under test verify(evaluator, times(1)) .routeReadingToEvaluator((PolicyRuleEvaluator)any(), eq(mockProvider)); assertThat(captorEvaluator.getValue(), is(not(nullValue()))); assertThat(captorEvaluator.getValue().getEvalSubject(), is(equalTo(fakeRules.iterator().next()))); } @Test public void testEvaluateNoRulesWithMultipleWildcard() { System.out.println("testEvaluateNoRulesWithMultipleWildcard"); final int operatorId = 1; MetricReading fakeReading = new MetricReading(); when(mockProvider.getOperatorId()).thenReturn(operatorId); when(mockProvider.nextReading()).thenReturn(fakeReading); PolicyRules fakeRules = new PolicyRules() {{ rule("CPU above 60% for 30 seconds") .scaleOut(allOperators()) .by(relative(2)).butNeverAbove(nodes(10)) .when(metric("cpu")) .is(above(percent(60))) .forAtLeast(seconds(30)).build(); rule("Memory above 1GB for 2 minutes") .scaleOut(allOperators()) .by(relative(4)).butNeverAbove(nodes(10)) .when(metric("memory")) .is(above(gb(1))) .forAtLeast(minutes(2)).build(); }}; PolicyRulesEvaluator evaluator = spy(new PolicyRulesEvaluator(fakeRules, mockAdaptor)); ArgumentCaptor<PolicyRuleEvaluator> captorEvaluator = ArgumentCaptor.forClass(PolicyRuleEvaluator.class); doNothing().when(evaluator) .routeReadingToEvaluator(captorEvaluator.capture(), eq(mockProvider)); evaluator.evaluate(mockProvider); // Assertions, make sure that routing method is invoked on object under test verify(evaluator, times(2)) .routeReadingToEvaluator((PolicyRuleEvaluator)any(), eq(mockProvider)); assertThat(captorEvaluator.getAllValues(), is(not(nullValue()))); assertThat(captorEvaluator.getAllValues().size(), is(equalTo(2))); Iterator<PolicyRule> it = fakeRules.iterator(); PolicyRule rule1 = it.next(); PolicyRule rule2 = it.next(); List<PolicyRule> actualRules = evaluatorsToRules(captorEvaluator.getAllValues()); assertThat(actualRules, containsInAnyOrder(rule1, rule2)); } @Test public void testEvaluateSingleRuleWithoutWildcard() { System.out.println("testEvaluateSingleRuleWithoutWildcard"); final int operatorId = 1; MetricReading fakeReading = new MetricReading(); when(mockProvider.getOperatorId()).thenReturn(operatorId); when(mockProvider.nextReading()).thenReturn(fakeReading); PolicyRules fakeRules = new PolicyRules() {{ rule("CPU above 60% for 30 seconds") .scaleOut(operator("Test operator", operatorId)) .by(relative(2)).butNeverAbove(nodes(10)) .when(metric("cpu")) .is(above(percent(60))) .forAtLeast(seconds(30)).build(); }}; PolicyRulesEvaluator evaluator = spy(new PolicyRulesEvaluator(fakeRules, mockAdaptor)); ArgumentCaptor<PolicyRuleEvaluator> captorEvaluator = ArgumentCaptor.forClass(PolicyRuleEvaluator.class); doNothing().when(evaluator) .routeReadingToEvaluator(captorEvaluator.capture(), eq(mockProvider)); evaluator.evaluate(mockProvider); // Assertions, make sure that routing method is invoked on object under test verify(evaluator, times(1)) .routeReadingToEvaluator((PolicyRuleEvaluator)any(), eq(mockProvider)); assertThat(captorEvaluator.getValue(), is(not(nullValue()))); assertThat(captorEvaluator.getValue().getEvalSubject(), is(equalTo(fakeRules.iterator().next()))); } @Test public void testEvaluateSingleRuleWithWildcard() { System.out.println("testEvaluateSingleRuleWithWildcard"); final int operatorId = 1; MetricReading fakeReading = new MetricReading(); when(mockProvider.getOperatorId()).thenReturn(operatorId); when(mockProvider.nextReading()).thenReturn(fakeReading); PolicyRules fakeRules = new PolicyRules() {{ rule("CPU above 60% for 30 seconds") .scaleOut(operator("Test operator", operatorId)) .by(relative(2)).butNeverAbove(nodes(10)) .when(metric("cpu")) .is(above(percent(60))) .forAtLeast(seconds(30)).build(); rule("Memory above 1GB for 2 minutes") .scaleOut(allOperators()) .by(relative(4)).butNeverAbove(nodes(10)) .when(metric("memory")) .is(above(gb(1))) .forAtLeast(minutes(2)).build(); }}; PolicyRulesEvaluator evaluator = spy(new PolicyRulesEvaluator(fakeRules, mockAdaptor)); ArgumentCaptor<PolicyRuleEvaluator> captorEvaluator = ArgumentCaptor.forClass(PolicyRuleEvaluator.class); doNothing().when(evaluator) .routeReadingToEvaluator(captorEvaluator.capture(), eq(mockProvider)); evaluator.evaluate(mockProvider); // Assertions, make sure that routing method is invoked on object under test verify(evaluator, times(2)) .routeReadingToEvaluator((PolicyRuleEvaluator)any(), eq(mockProvider)); assertThat(captorEvaluator.getAllValues(), is(not(nullValue()))); assertThat(captorEvaluator.getAllValues().size(), is(equalTo(2))); Iterator<PolicyRule> it = fakeRules.iterator(); PolicyRule rule1 = it.next(); PolicyRule rule2 = it.next(); List<PolicyRule> actualRules = evaluatorsToRules(captorEvaluator.getAllValues()); assertThat(actualRules, containsInAnyOrder(rule1, rule2)); } @Test public void testEvaluateMultipleRulesWithoutWildcard() { System.out.println("testEvaluateMultipleRulesWithoutWildcard"); final int[] operatorIds = new int[] {1, 2, 3}; final MetricReading[] fakeReadings = new MetricReading[] { new MetricReading(), new MetricReading(), new MetricReading()}; when(mockProvider.getOperatorId()) .thenReturn(operatorIds[0]) .thenReturn(operatorIds[1]) .thenReturn(operatorIds[2]); when(mockProvider.nextReading()) .thenReturn(fakeReadings[0]) .thenReturn(fakeReadings[1]) .thenReturn(fakeReadings[2]); PolicyRules fakeRules = new PolicyRules() {{ rule("CPU above 60% for 30 seconds") .scaleOut(operator("Test operator #1", operatorIds[0])) .by(relative(2)).butNeverAbove(nodes(10)) .when(metric("cpu")) .is(above(percent(60))) .forAtLeast(seconds(30)).build(); rule("Memory above 1GB for 2 minutes") .scaleOut(operator("Test operator #2", operatorIds[1])) .by(relative(4)).butNeverAbove(nodes(10)) .when(metric("memory")) .is(above(gb(1))) .forAtLeast(minutes(2)).build(); rule("Memory below 512MB for 5 minutes") .scaleIn(operator("Test operator #3", operatorIds[2])) .by(relative(2)) .when(metric("memory")) .is(below(mb(512))) .forAtLeast(minutes(5)).build(); }}; Iterator<PolicyRule> it = fakeRules.iterator(); PolicyRule rule1 = it.next(); PolicyRule rule2 = it.next(); PolicyRule rule3 = it.next(); PolicyRulesEvaluator evaluator = spy(new PolicyRulesEvaluator(fakeRules, mockAdaptor)); ArgumentCaptor<PolicyRuleEvaluator> captorEvaluator = ArgumentCaptor.forClass(PolicyRuleEvaluator.class); doNothing().when(evaluator) .routeReadingToEvaluator(captorEvaluator.capture(), eq(mockProvider)); evaluator.evaluate(mockProvider); // operatorId = 1 evaluator.evaluate(mockProvider); // operatorId = 2 evaluator.evaluate(mockProvider); // operatorId = 3 // Make sure all offered readings are routed verify(evaluator, times(3)) .routeReadingToEvaluator((PolicyRuleEvaluator)any(), eq(mockProvider)); assertThat(captorEvaluator.getAllValues(), is(not(nullValue()))); assertThat(captorEvaluator.getAllValues().size(), is(equalTo(3))); // Check evaluators are captured for all rules and in the correct order List<PolicyRule> actualRules = evaluatorsToRules(captorEvaluator.getAllValues()); assertThat(actualRules, contains(rule1, rule2, rule3)); } @Test public void testEvaluateMultipleRulesWithWildcard() { System.out.println("testEvaluateMultipleRulesWithWildcard"); final int[] operatorIds = new int[] {1, 2, 3}; final MetricReading[] fakeReadings = new MetricReading[] { new MetricReading(), new MetricReading(), new MetricReading()}; when(mockProvider.getOperatorId()) .thenReturn(operatorIds[0]) .thenReturn(operatorIds[1]) .thenReturn(operatorIds[2]); when(mockProvider.nextReading()) .thenReturn(fakeReadings[0]) .thenReturn(fakeReadings[1]) .thenReturn(fakeReadings[2]); PolicyRules fakeRules = new PolicyRules() {{ rule("CPU above 60% for 30 seconds") .scaleOut(operator("Test operator #1", operatorIds[0])) .by(relative(2)).butNeverAbove(nodes(10)) .when(metric("cpu")) .is(above(percent(60))) .forAtLeast(seconds(30)).build(); rule("Memory above 1GB for 2 minutes") .scaleOut(operator("Test operator #2", operatorIds[1])) .by(relative(4)).butNeverAbove(nodes(10)) .when(metric("memory")) .is(above(gb(1))) .forAtLeast(minutes(2)).build(); rule("Memory below 512MB for 5 minutes") .scaleIn(operator("Test operator #3", operatorIds[2])) .by(relative(2)) .when(metric("memory")) .is(below(mb(512))) .forAtLeast(minutes(5)).build(); rule("Latency exceeds 500 ms for 3 minutes") .scaleOut(allOperators()) .by(absolute(1)).butNeverAbove(nodes(20)) .when(metric("latency")) .is(above(millis(500))) .forAtLeast(minutes(3)).build(); }}; Iterator<PolicyRule> it = fakeRules.iterator(); PolicyRule rule1 = it.next(); PolicyRule rule2 = it.next(); PolicyRule rule3 = it.next(); PolicyRule ruleAll = it.next(); PolicyRulesEvaluator evaluator = spy(new PolicyRulesEvaluator(fakeRules, mockAdaptor)); ArgumentCaptor<PolicyRuleEvaluator> captorEvaluator = ArgumentCaptor.forClass(PolicyRuleEvaluator.class); doNothing().when(evaluator) .routeReadingToEvaluator(captorEvaluator.capture(), eq(mockProvider)); evaluator.evaluate(mockProvider); // operatorId = 1 evaluator.evaluate(mockProvider); // operatorId = 2 evaluator.evaluate(mockProvider); // operatorId = 3 // Make sure all offered readings are routed verify(evaluator, times(6)) .routeReadingToEvaluator((PolicyRuleEvaluator)any(), eq(mockProvider)); assertThat(captorEvaluator.getAllValues(), is(not(nullValue()))); assertThat(captorEvaluator.getAllValues().size(), is(equalTo(6))); // Check evaluators are captured for all rules and in the correct order List<PolicyRule> actualRules = evaluatorsToRules(captorEvaluator.getAllValues()); assertThat(actualRules, contains(rule1, ruleAll, rule2, ruleAll, rule3, ruleAll)); } @Test public void testEvaluateMultipleRulesForSameOperator() { System.out.println("testEvaluateMultipleRulesForSameOperator"); final int operatorId = 1; MetricReading fakeReading = new MetricReading(); when(mockProvider.getOperatorId()).thenReturn(operatorId); when(mockProvider.nextReading()).thenReturn(fakeReading); PolicyRules fakeRules = new PolicyRules() {{ rule("CPU above 60% for 30 seconds") .scaleOut(operator("Test operator", operatorId)) .by(relative(2)).butNeverAbove(nodes(10)) .when(metric("cpu")) .is(above(percent(60))) .forAtLeast(seconds(30)).build(); rule("Memory above 1GB for 2 minutes") .scaleOut(operator("Test operator", operatorId)) .by(relative(4)).butNeverAbove(nodes(10)) .when(metric("memory")) .is(above(gb(1))) .forAtLeast(minutes(2)).build(); }}; Iterator<PolicyRule> it = fakeRules.iterator(); PolicyRule rule1 = it.next(); PolicyRule rule2 = it.next(); PolicyRulesEvaluator evaluator = spy(new PolicyRulesEvaluator(fakeRules, mockAdaptor)); ArgumentCaptor<PolicyRuleEvaluator> captorEvaluator = ArgumentCaptor.forClass(PolicyRuleEvaluator.class); doNothing().when(evaluator) .routeReadingToEvaluator(captorEvaluator.capture(), eq(mockProvider)); evaluator.evaluate(mockProvider); // Assertions, make sure that routing method is invoked on object under test verify(evaluator, times(2)) .routeReadingToEvaluator((PolicyRuleEvaluator)any(), eq(mockProvider)); assertThat(captorEvaluator.getAllValues(), is(not(nullValue()))); assertThat(captorEvaluator.getAllValues().size(), is(equalTo(2))); // Check evaluators are captured for all rules and in the correct order List<PolicyRule> actualRules = evaluatorsToRules(captorEvaluator.getAllValues()); assertThat(actualRules, contains(rule1, rule2)); } @Test public void testEvaluateMultipleRulesWithMultipleWildcard() { System.out.println("testEvaluateMultipleRulesWithMultipleWildcard"); final int[] operatorIds = new int[] {1, 2, 3}; final MetricReading[] fakeReadings = new MetricReading[] { new MetricReading(), new MetricReading(), new MetricReading()}; when(mockProvider.getOperatorId()) .thenReturn(operatorIds[0]) .thenReturn(operatorIds[1]) .thenReturn(operatorIds[2]); when(mockProvider.nextReading()) .thenReturn(fakeReadings[0]) .thenReturn(fakeReadings[1]) .thenReturn(fakeReadings[2]); PolicyRules fakeRules = new PolicyRules() {{ rule("CPU above 60% for 30 seconds") .scaleOut(operator("Test operator #1", operatorIds[0])) .by(relative(2)).butNeverAbove(nodes(10)) .when(metric("cpu")) .is(above(percent(60))) .forAtLeast(seconds(30)).build(); rule("Memory above 1GB for 2 minutes") .scaleOut(operator("Test operator #2", operatorIds[1])) .by(relative(4)).butNeverAbove(nodes(10)) .when(metric("memory")) .is(above(gb(1))) .forAtLeast(minutes(2)).build(); rule("Memory below 512MB for 5 minutes") .scaleIn(operator("Test operator #3", operatorIds[2])) .by(relative(2)) .when(metric("memory")) .is(below(mb(512))) .forAtLeast(minutes(5)).build(); rule("Latency exceeds 500 ms for 3 minutes") .scaleOut(allOperators()) .by(absolute(1)).butNeverAbove(nodes(20)) .when(metric("latency")) .is(above(millis(500))) .forAtLeast(minutes(3)).build(); rule("Queue exceeds 1000 tuples for 1 minute") .scaleOut(allOperators()) .by(absolute(1)) .when(metric("queue-length")) .is(above(tuples(1000))) .forAtLeast(seconds(60)).build(); }}; Iterator<PolicyRule> it = fakeRules.iterator(); PolicyRule rule1 = it.next(); PolicyRule rule2 = it.next(); PolicyRule rule3 = it.next(); PolicyRule ruleAll1 = it.next(); PolicyRule ruleAll2 = it.next(); PolicyRulesEvaluator evaluator = spy(new PolicyRulesEvaluator(fakeRules, mockAdaptor)); ArgumentCaptor<PolicyRuleEvaluator> captorEvaluator = ArgumentCaptor.forClass(PolicyRuleEvaluator.class); doNothing().when(evaluator) .routeReadingToEvaluator(captorEvaluator.capture(), eq(mockProvider)); evaluator.evaluate(mockProvider); // operatorId = 1 evaluator.evaluate(mockProvider); // operatorId = 2 evaluator.evaluate(mockProvider); // operatorId = 3 // Make sure all offered readings are routed verify(evaluator, times(9)) .routeReadingToEvaluator((PolicyRuleEvaluator)any(), eq(mockProvider)); assertThat(captorEvaluator.getAllValues(), is(not(nullValue()))); assertThat(captorEvaluator.getAllValues().size(), is(equalTo(9))); // Check evaluators are captured for all rules and in the correct order List<PolicyRule> actualRules = evaluatorsToRules(captorEvaluator.getAllValues()); assertThat(actualRules, contains(rule1, ruleAll1, ruleAll2, rule2, ruleAll1, ruleAll2, rule3, ruleAll1, ruleAll2)); } }