// This file is part of OpenTSDB.
// Copyright (C) 2015 The OpenTSDB Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2.1 of the License, or (at your
// option) any later version. This program is distributed in the hope that it
// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
// General Public License for more details. You should have received a copy
// of the GNU Lesser General Public License along with this program. If not,
// see <http://www.gnu.org/licenses/>.
package net.opentsdb.query.expression;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import net.opentsdb.core.DataPoint;
import net.opentsdb.core.DataPoints;
import net.opentsdb.core.MutableDataPoint;
import net.opentsdb.core.SeekableView;
import net.opentsdb.meta.Annotation;
import org.hbase.async.Bytes.ByteMap;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.stumbleupon.async.Deferred;
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"javax.management.*", "javax.xml.*",
"ch.qos.*", "org.slf4j.*",
"com.sum.*", "org.xml.*"})
@PrepareForTest({ Annotation.class })
public class TestPostAggregatedDataPoints {
private static int NUM_POINTS = 5;
private static String METRIC_NAME = "sys.cpu";
private static long BASE_TIME = 1356998400000L;
private static int TIME_INTERVAL = 60000;
private DataPoints base_data_points;
private DataPoint[] points;
private Map<String, String> tags;
private List<String> agg_tags;
private List<String> tsuids;
private List<Annotation> annotations;
private ByteMap<byte[]> tag_uids;
@Before
public void before() throws Exception {
base_data_points = PowerMockito.mock(DataPoints.class);
points = new MutableDataPoint[NUM_POINTS];
long ts = BASE_TIME;
for (int i = 0; i < NUM_POINTS; i++) {
MutableDataPoint mdp = new MutableDataPoint();
mdp.reset(ts, i);
points[i] = mdp;
ts += TIME_INTERVAL;
}
tags = new HashMap<String, String>(1);
tags.put("colo", "lga");
agg_tags = new ArrayList<String>(1);
agg_tags.add("host");
tsuids = new ArrayList<String>(1);
tsuids.add("0101010202"); // just 1 byte UIDs for kicks
annotations = new ArrayList<Annotation>(1);
annotations.add(PowerMockito.mock(Annotation.class));
tag_uids = new ByteMap<byte[]>();
tag_uids.put(new byte[] { 1 }, new byte[] { 1 });
when(base_data_points.metricName()).thenReturn(METRIC_NAME);
when(base_data_points.metricNameAsync()).thenReturn(
Deferred.fromResult(METRIC_NAME));
when(base_data_points.getTags()).thenReturn(tags);
when(base_data_points.getTagsAsync()).thenReturn(Deferred.fromResult(tags));
when(base_data_points.getAggregatedTags()).thenReturn(agg_tags);
when(base_data_points.getAggregatedTagsAsync()).thenReturn(
Deferred.fromResult(agg_tags));
when(base_data_points.getTSUIDs()).thenReturn(tsuids);
when(base_data_points.getAnnotations()).thenReturn(annotations);
when(base_data_points.getTagUids()).thenReturn(tag_uids);
when(base_data_points.getQueryIndex()).thenReturn(42);
}
@Test
public void ctorDefaults() throws Exception {
final PostAggregatedDataPoints dps = new PostAggregatedDataPoints(
base_data_points, points);
assertEquals(METRIC_NAME, dps.metricName());
assertEquals(METRIC_NAME, dps.metricNameAsync().join());
assertSame(tags, dps.getTags());
assertSame(tags, dps.getTagsAsync().join());
assertSame(agg_tags, dps.getAggregatedTags());
assertSame(agg_tags, dps.getAggregatedTagsAsync().join());
assertSame(tsuids, dps.getTSUIDs());
assertSame(annotations, dps.getAnnotations());
assertSame(tag_uids, dps.getTagUids());
assertEquals(42, dps.getQueryIndex());
assertEquals(5, dps.size());
assertEquals(5, dps.aggregatedSize());
// values
final SeekableView iterator = dps.iterator();
int values = 0;
long value = 0;
long ts = BASE_TIME;
while(iterator.hasNext()) {
final DataPoint dp = iterator.next();
assertEquals(value++, dp.longValue());
assertEquals(ts, dp.timestamp());
ts += TIME_INTERVAL;
values++;
}
assertEquals(5, values);
assertFalse(iterator.hasNext());
try {
iterator.next();
fail("Expected a NoSuchElementException");
} catch (NoSuchElementException e) { }
assertEquals(BASE_TIME + (4 * TIME_INTERVAL), dps.timestamp(4));
assertEquals(4, dps.longValue(4));
assertTrue(dps.isInteger(4));
try {
assertEquals(4, dps.doubleValue(4), 0.00);
fail("Expected a ClassCastException");
} catch (ClassCastException e) { }
try {
dps.timestamp(5);
fail("Expected a ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) { }
try {
dps.isInteger(5);
fail("Expected a ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) { }
try {
dps.longValue(5);
fail("Expected a ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) { }
try {
dps.doubleValue(5);
fail("Expected a ArrayIndexOutOfBoundsException");
} catch (ArrayIndexOutOfBoundsException e) { }
}
@Test (expected = IllegalArgumentException.class)
public void ctorNullBase() throws Exception {
new PostAggregatedDataPoints(null, points);
}
@Test (expected = IllegalArgumentException.class)
public void ctorNullPoints() throws Exception {
new PostAggregatedDataPoints(base_data_points, null);
}
@Test
public void alias() throws Exception {
final PostAggregatedDataPoints dps = new PostAggregatedDataPoints(
base_data_points, points);
final String alias = "ein";
dps.setAlias(alias);
assertEquals(alias, dps.metricName());
assertEquals(alias, dps.metricNameAsync().join());
assertTrue(dps.getTags().isEmpty());
assertTrue(dps.getTagsAsync().join().isEmpty());
assertTrue(dps.getAggregatedTags().isEmpty());
assertTrue(dps.getAggregatedTagsAsync().join().isEmpty());
assertSame(tsuids, dps.getTSUIDs());
assertSame(annotations, dps.getAnnotations());
assertSame(tag_uids, dps.getTagUids());
assertEquals(42, dps.getQueryIndex());
assertEquals(5, dps.size());
assertEquals(5, dps.aggregatedSize());
}
@Test
public void emptyPoints() throws Exception {
points = new MutableDataPoint[0];
final PostAggregatedDataPoints dps = new PostAggregatedDataPoints(
base_data_points, points);
assertEquals(METRIC_NAME, dps.metricName());
assertEquals(METRIC_NAME, dps.metricNameAsync().join());
assertSame(tags, dps.getTags());
assertSame(tags, dps.getTagsAsync().join());
assertSame(agg_tags, dps.getAggregatedTags());
assertSame(agg_tags, dps.getAggregatedTagsAsync().join());
assertSame(tsuids, dps.getTSUIDs());
assertSame(annotations, dps.getAnnotations());
assertSame(tag_uids, dps.getTagUids());
assertEquals(42, dps.getQueryIndex());
assertEquals(0, dps.size());
assertEquals(0, dps.aggregatedSize());
// values
final SeekableView iterator = dps.iterator();
assertFalse(iterator.hasNext());
try {
iterator.next();
fail("Expected a NoSuchElementException");
} catch (NoSuchElementException e) { }
}
}