diff --git a/src/test/java/org/elasticsearch/alerts/throttle/AckThrottlerTests.java b/src/test/java/org/elasticsearch/alerts/throttle/AckThrottlerTests.java new file mode 100644 index 00000000000..45001ff365a --- /dev/null +++ b/src/test/java/org/elasticsearch/alerts/throttle/AckThrottlerTests.java @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.alerts.throttle; + +import org.elasticsearch.alerts.Alert; +import org.elasticsearch.alerts.ExecutionContext; +import org.elasticsearch.common.joda.time.DateTime; +import org.elasticsearch.test.ElasticsearchTestCase; +import org.junit.Test; + +import static org.elasticsearch.alerts.support.AlertsDateUtils.formatDate; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * + */ +public class AckThrottlerTests extends ElasticsearchTestCase { + + @Test + public void testWhenAcked() throws Exception { + DateTime timestamp = new DateTime(); + ExecutionContext ctx = mock(ExecutionContext.class); + Alert alert = mock(Alert.class); + Alert.Status status = mock(Alert.Status.class); + when(status.ackStatus()).thenReturn(new Alert.Status.AckStatus(Alert.Status.AckStatus.State.ACKED, timestamp)); + when(alert.status()).thenReturn(status); + when(alert.name()).thenReturn("_alert"); + when(alert.acked()).thenReturn(true); + when(ctx.alert()).thenReturn(alert); + AckThrottler throttler = new AckThrottler(); + Throttler.Result result = throttler.throttle(ctx); + assertThat(result.throttle(), is(true)); + assertThat(result.reason(), is("alert [_alert] was acked at [" + formatDate(timestamp) + "]")); + } + + @Test + public void testWhenNotAcked() throws Exception { + DateTime timestamp = new DateTime(); + ExecutionContext ctx = mock(ExecutionContext.class); + Alert alert = mock(Alert.class); + Alert.Status status = mock(Alert.Status.class); + Alert.Status.AckStatus.State state = randomFrom(Alert.Status.AckStatus.State.AWAITS_EXECUTION, Alert.Status.AckStatus.State.ACKABLE); + when(status.ackStatus()).thenReturn(new Alert.Status.AckStatus(state, timestamp)); + when(alert.status()).thenReturn(status); + when(alert.name()).thenReturn("_alert"); + when(alert.acked()).thenReturn(false); + when(ctx.alert()).thenReturn(alert); + AckThrottler throttler = new AckThrottler(); + Throttler.Result result = throttler.throttle(ctx); + assertThat(result.throttle(), is(false)); + assertThat(result.reason(), nullValue()); + } +} diff --git a/src/test/java/org/elasticsearch/alerts/throttle/AlertThrottlerTests.java b/src/test/java/org/elasticsearch/alerts/throttle/AlertThrottlerTests.java new file mode 100644 index 00000000000..37fb496e75a --- /dev/null +++ b/src/test/java/org/elasticsearch/alerts/throttle/AlertThrottlerTests.java @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.alerts.throttle; + +import org.elasticsearch.alerts.ExecutionContext; +import org.elasticsearch.test.ElasticsearchTestCase; +import org.junit.Test; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.sameInstance; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * + */ +public class AlertThrottlerTests extends ElasticsearchTestCase { + + @Test + public void testThrottle_DueToAck() throws Exception { + PeriodThrottler periodThrottler = mock(PeriodThrottler.class); + AckThrottler ackThrottler = mock(AckThrottler.class); + ExecutionContext ctx = mock(ExecutionContext.class); + when(periodThrottler.throttle(ctx)).thenReturn(Throttler.Result.NO); + Throttler.Result expectedResult = Throttler.Result.throttle("_reason"); + when(ackThrottler.throttle(ctx)).thenReturn(expectedResult); + AlertThrottler throttler = new AlertThrottler(periodThrottler, ackThrottler); + Throttler.Result result = throttler.throttle(ctx); + assertThat(result, notNullValue()); + assertThat(result, is(expectedResult)); + } + + @Test + public void testThrottle_DueToPeriod() throws Exception { + PeriodThrottler periodThrottler = mock(PeriodThrottler.class); + AckThrottler ackThrottler = mock(AckThrottler.class); + ExecutionContext ctx = mock(ExecutionContext.class); + Throttler.Result expectedResult = Throttler.Result.throttle("_reason"); + when(periodThrottler.throttle(ctx)).thenReturn(expectedResult); + when(ackThrottler.throttle(ctx)).thenReturn(Throttler.Result.NO); + AlertThrottler throttler = new AlertThrottler(periodThrottler, ackThrottler); + Throttler.Result result = throttler.throttle(ctx); + assertThat(result, notNullValue()); + assertThat(result, is(expectedResult)); + } + + @Test + public void testThrottle_DueBoth() throws Exception { + PeriodThrottler periodThrottler = mock(PeriodThrottler.class); + AckThrottler ackThrottler = mock(AckThrottler.class); + ExecutionContext ctx = mock(ExecutionContext.class); + Throttler.Result periodResult = Throttler.Result.throttle("_reason_period"); + when(periodThrottler.throttle(ctx)).thenReturn(periodResult); + Throttler.Result ackResult = Throttler.Result.throttle("_reason_ack"); + when(ackThrottler.throttle(ctx)).thenReturn(ackResult); + AlertThrottler throttler = new AlertThrottler(periodThrottler, ackThrottler); + Throttler.Result result = throttler.throttle(ctx); + assertThat(result, notNullValue()); + // we always check the period first... so the result will come for the period throttler + assertThat(result, is(periodResult)); + } + + @Test + public void testNoThrottle() throws Exception { + PeriodThrottler periodThrottler = mock(PeriodThrottler.class); + AckThrottler ackThrottler = mock(AckThrottler.class); + ExecutionContext ctx = mock(ExecutionContext.class); + when(periodThrottler.throttle(ctx)).thenReturn(Throttler.Result.NO); + when(ackThrottler.throttle(ctx)).thenReturn(Throttler.Result.NO); + AlertThrottler throttler = new AlertThrottler(periodThrottler, ackThrottler); + Throttler.Result result = throttler.throttle(ctx); + assertThat(result, notNullValue()); + assertThat(result, is(Throttler.Result.NO)); + } + + @Test + public void testWithoutPeriod() throws Exception { + AckThrottler ackThrottler = mock(AckThrottler.class); + ExecutionContext ctx = mock(ExecutionContext.class); + Throttler.Result ackResult = mock(Throttler.Result.class); + when(ackThrottler.throttle(ctx)).thenReturn(ackResult); + AlertThrottler throttler = new AlertThrottler(null, ackThrottler); + Throttler.Result result = throttler.throttle(ctx); + assertThat(result, notNullValue()); + assertThat(result, sameInstance(ackResult)); + } +} diff --git a/src/test/java/org/elasticsearch/alerts/throttle/PeriodThrottlerTests.java b/src/test/java/org/elasticsearch/alerts/throttle/PeriodThrottlerTests.java new file mode 100644 index 00000000000..6bd84b69613 --- /dev/null +++ b/src/test/java/org/elasticsearch/alerts/throttle/PeriodThrottlerTests.java @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.alerts.throttle; + +import com.carrotsearch.randomizedtesting.annotations.Repeat; +import org.elasticsearch.alerts.Alert; +import org.elasticsearch.alerts.ExecutionContext; +import org.elasticsearch.common.joda.time.DateTime; +import org.elasticsearch.common.joda.time.PeriodType; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.test.ElasticsearchTestCase; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.startsWith; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * + */ +public class PeriodThrottlerTests extends ElasticsearchTestCase { + + @Test @Repeat(iterations = 10) + public void testBelowPeriod() throws Exception { + PeriodType periodType = randomFrom(PeriodType.millis(), PeriodType.seconds(), PeriodType.minutes()); + TimeValue period = TimeValue.timeValueSeconds(randomIntBetween(2, 5)); + PeriodThrottler throttler = new PeriodThrottler(period, periodType); + + ExecutionContext ctx = mock(ExecutionContext.class); + Alert alert = mock(Alert.class); + Alert.Status status = mock(Alert.Status.class); + when(ctx.alert()).thenReturn(alert); + when(alert.status()).thenReturn(status); + when(status.lastExecuted()).thenReturn(new DateTime().minusSeconds((int) period.seconds() - 1)); + + Throttler.Result result = throttler.throttle(ctx); + assertThat(result, notNullValue()); + assertThat(result.throttle(), is(true)); + assertThat(result.reason(), notNullValue()); + assertThat(result.reason(), startsWith("throttling interval is set to [" + period.format(periodType) + "]")); + } + + @Test @Repeat(iterations = 10) + public void testAbovePeriod() throws Exception { + PeriodType periodType = randomFrom(PeriodType.millis(), PeriodType.seconds(), PeriodType.minutes()); + TimeValue period = TimeValue.timeValueSeconds(randomIntBetween(2, 5)); + PeriodThrottler throttler = new PeriodThrottler(period, periodType); + + ExecutionContext ctx = mock(ExecutionContext.class); + Alert alert = mock(Alert.class); + Alert.Status status = mock(Alert.Status.class); + when(ctx.alert()).thenReturn(alert); + when(alert.status()).thenReturn(status); + when(status.lastExecuted()).thenReturn(new DateTime().minusSeconds((int) period.seconds() + 1)); + + Throttler.Result result = throttler.throttle(ctx); + assertThat(result, notNullValue()); + assertThat(result.throttle(), is(false)); + assertThat(result.reason(), nullValue()); + } + +}