/*
* Copyright 2011-2013 the original author or authors.
*
* 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.
*/
package org.springframework.xd.analytics.metrics;
import static org.junit.Assert.assertEquals;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.Interval;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.xd.analytics.metrics.core.AggregateCount;
import org.springframework.xd.analytics.metrics.core.AggregateCountResolution;
import org.springframework.xd.analytics.metrics.core.AggregateCounterRepository;
/**
* @author Luke Taylor
* @author Gary Russell
* @author Ilayaperumal Gopinathan
*/
public abstract class AbstractAggregateCounterTests {
protected final String counterName = "test";
@Autowired
protected AggregateCounterRepository aggregateCounterRepository;
@Test
public void test66MinuteCount() throws Exception {
final DateTime start = new DateTime(2013, 6, 28, 23, 0, 0, 0);
final DateTime end = start.plusMinutes(66);
DateTime now = start;
int val = 1;
while (now.isBefore(end)) {
aggregateCounterRepository.increment(counterName, val++, now);
now = now.plus(Duration.standardMinutes(1));
}
// Include 66th minute's value
aggregateCounterRepository.increment(counterName, val++, now);
long[] counts = aggregateCounterRepository.getCounts(counterName, new Interval(start, end), AggregateCountResolution.minute).getCounts();
// the counts.length should be 66 + 1 to include the 66th minute's count
assertEquals(67, counts.length);
assertEquals(1, counts[0]);
assertEquals(66, counts[65]);
assertEquals(67, counts[66]);
}
@Test
public void testDayCounts() throws Exception {
final DateTime start = new DateTime(2013, 11, 28, 23, 0);
final DateTime end = start.plusDays(66);
DateTime now = start;
int val = 1;
while (!now.isAfter(end.plusDays(1))) {
aggregateCounterRepository.increment(counterName, val++, now);
now = now.plus(Duration.standardDays(1));
}
long[] counts = aggregateCounterRepository.getCounts(counterName, new Interval(start, end), AggregateCountResolution.day).getCounts();
assertEquals(67, counts.length);
for (int i=0; i < counts.length; i++) {
assertEquals("count at index " + i + " should be " + (i+1), i+1, counts[i]);
}
counts = aggregateCounterRepository.getCounts(counterName, new Interval(end.minusDays(30), end), AggregateCountResolution.day).getCounts();
assertEquals(31, counts.length);
counts = aggregateCounterRepository.getCounts(counterName, 60, end, AggregateCountResolution.day).getCounts();
assertEquals(60, counts.length);
assertEquals(8, counts[0]);
assertEquals(67, counts[59]);
}
@Test
public void testMonthCounts() throws Exception {
final DateTime start = new DateTime(2013, 11, 20, 0, 0);
final DateTime end = start.plusMonths(5);
int val = 1;
for (DateTime now = start; !now.isAfter(end); now = now.plusMonths(1)) {
aggregateCounterRepository.increment(counterName, val++, now);
}
long[] counts = aggregateCounterRepository.getCounts(counterName, new Interval(start,end), AggregateCountResolution.month).getCounts();
assertEquals(6, counts.length);
for (int i = 0; i < counts.length; i++) {
assertEquals("count at index " + i + " should be " + (i + 1), i + 1, counts[i]);
}
// Check a query for twelve months past
counts = aggregateCounterRepository.getCounts(counterName, new Interval(end.minusMonths(11), end), AggregateCountResolution.month).getCounts();
assertEquals(12, counts.length);
counts = aggregateCounterRepository.getCounts(counterName, 3, end, AggregateCountResolution.month).getCounts();
assertEquals(3, counts.length);
assertEquals(6, counts[2]);
}
@Test
public void testYearCounts() throws Exception {
final DateTime start = new DateTime(2013, 11, 20, 0, 0);
final DateTime end = start.plusYears(5);
int val = 1;
for (DateTime now = start; !now.isAfter(end); now = now.plusYears(1)) {
aggregateCounterRepository.increment(counterName, val++, now);
}
long[] counts = aggregateCounterRepository.getCounts(counterName, new Interval(start,end), AggregateCountResolution.year).getCounts();
assertEquals(6, counts.length);
assertEquals(6, counts[5]);
assertEquals(1, counts[0]);
}
@Test
public void testTwoDaysDataSimulation() throws Exception {
final DateTime start = new DateTime(2013, 12, 30, 23, 27);
final DateTime end = start.plusDays(2);
DateTime now = start;
int total = 0;
while (now.isBefore(end)) {
int minute = now.getMinuteOfHour();
aggregateCounterRepository.increment(counterName, minute, now);
now = now.plusMinutes(1);
total += minute;
}
// Include end time's metric
int endMinute = end.getMinuteOfHour();
aggregateCounterRepository.increment(counterName, endMinute, now);
total += endMinute;
// Check the total
assertEquals(total, aggregateCounterRepository.findOne(counterName).getValue());
// Query the entire period
Interval queryInterval = new Interval(start, end);
AggregateCount aggregateCount = aggregateCounterRepository.getCounts(counterName, queryInterval,
AggregateCountResolution.minute);
assertEquals(counterName, aggregateCount.getName());
assertEquals(queryInterval, aggregateCount.getInterval());
long[] counts = aggregateCount.getCounts();
// counts.length should include the end time's minute
assertEquals((2 * 24 * 60) + 1, counts.length);
assertEquals(27, counts[0]);
assertEquals(28, counts[1]);
assertEquals(59, counts[32]);
for (int i = 33; i < counts.length; i++) {
int expect = (i - 33) % 60;
assertEquals("Count at index " + i + " should be " + expect, expect, counts[i]);
}
// Query a 24 hour period in minutes
now = start.plusHours(5).withMinuteOfHour(0);
queryInterval = new Interval(now, now.plusHours(24));
aggregateCount = aggregateCounterRepository.getCounts(counterName, queryInterval, AggregateCountResolution.minute);
counts = aggregateCount.getCounts();
// Add 'now.plusHours(24)' minute time to the count
assertEquals((24 * 60) + 1, counts.length);
assertEquals(0, counts[0]); // on an hour boundary
for (int i = 1; i < counts.length; i++) {
int expect = i % 60;
assertEquals("Count at index " + i + " should be " + expect, expect, counts[i]);
}
// Query the entire period in hours
queryInterval = new Interval(start, end);
aggregateCount = aggregateCounterRepository.getCounts(counterName, queryInterval, AggregateCountResolution.hour);
counts = aggregateCount.getCounts();
assertEquals(49, counts.length);
// The first hour starts before the first counts are added
assertEquals(1419, counts[0]); // sum [27..59]
for (int i = 1; i < (counts.length - 1); i++) {
assertEquals(1770, counts[i]); // sum [0..59]
}
// The last hour ends at 27th minute
assertEquals(378, counts[counts.length - 1]); // sum [0..27]
// Query the entire period in days
aggregateCount = aggregateCounterRepository.getCounts(counterName, queryInterval, AggregateCountResolution.day);
counts = aggregateCount.getCounts();
assertEquals(3, counts.length);
// Query beyond the period where we have data
DateTime newStart = start.withYear(2012);
aggregateCount = aggregateCounterRepository.getCounts(counterName, queryInterval.withStart(newStart), AggregateCountResolution.day);
counts = aggregateCount.getCounts();
assertEquals(368, counts.length);
aggregateCount = aggregateCounterRepository.getCounts(counterName, queryInterval.withStart(newStart), AggregateCountResolution.month);
}
}