// This file is part of OpenTSDB.
// Copyright (C) 2013 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.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.opentsdb.query.filter.TagVFilter;
import net.opentsdb.query.filter.TagVLiteralOrFilter;
import net.opentsdb.query.filter.TagVWildcardFilter;
import org.junit.Test;
public final class TestTSSubQuery {
@Test
public void constructor() {
assertNotNull(new TSSubQuery());
}
@Test
public void validate() {
TSSubQuery sub = getMetricForValidate();
sub.validateAndSetQuery();
assertEquals("sys.cpu.0", sub.getMetric());
assertEquals("wildcard(*)", sub.getTags().get("host"));
assertEquals("literal_or(lga)", sub.getTags().get("dc"));
assertEquals(Aggregators.SUM, sub.aggregator());
assertEquals(Aggregators.AVG, sub.downsampler());
assertEquals(300000, sub.downsampleInterval());
}
@Test
public void validateTS() {
TSSubQuery sub = getMetricForValidate();
sub.setMetric(null);
ArrayList<String> tsuids = new ArrayList<String>(1);
tsuids.add("ABCD");
sub.setTsuids(tsuids);
sub.validateAndSetQuery();
assertNotNull(sub.getTsuids());
assertEquals("wildcard(*)", sub.getTags().get("host"));
assertEquals("literal_or(lga)", sub.getTags().get("dc"));
assertEquals(Aggregators.SUM, sub.aggregator());
assertEquals(Aggregators.AVG, sub.downsampler());
assertEquals(300000, sub.downsampleInterval());
}
@Test
public void validateNoDS() {
TSSubQuery sub = getMetricForValidate();
sub.setDownsample(null);
sub.validateAndSetQuery();
assertEquals("sys.cpu.0", sub.getMetric());
assertEquals("wildcard(*)", sub.getTags().get("host"));
assertEquals("literal_or(lga)", sub.getTags().get("dc"));
assertEquals(Aggregators.SUM, sub.aggregator());
assertNull(sub.downsampler());
assertEquals(0, sub.downsampleInterval());
}
@Test (expected = IllegalArgumentException.class)
public void validateNullAgg() {
TSSubQuery sub = getMetricForValidate();
sub.setAggregator(null);
sub.validateAndSetQuery();
}
@Test (expected = IllegalArgumentException.class)
public void validateEmptyAgg() {
TSSubQuery sub = getMetricForValidate();
sub.setAggregator("");
sub.validateAndSetQuery();
}
@Test (expected = IllegalArgumentException.class)
public void validateBadAgg() {
TSSubQuery sub = getMetricForValidate();
sub.setAggregator("Notanagg");
sub.validateAndSetQuery();
}
@Test (expected = IllegalArgumentException.class)
public void validateNoMetricOrTsuids() {
TSSubQuery sub = getMetricForValidate();
sub.setMetric(null);
sub.setTsuids(null);
sub.validateAndSetQuery();
}
@Test (expected = IllegalArgumentException.class)
public void validateNoMetricOrEmptyTsuids() {
TSSubQuery sub = getMetricForValidate();
sub.setMetric(null);
sub.setTsuids(new ArrayList<String>());
sub.validateAndSetQuery();
}
@Test (expected = IllegalArgumentException.class)
public void validateBadDS() {
TSSubQuery sub = getMetricForValidate();
sub.setDownsample("bad");
sub.validateAndSetQuery();
}
@Test
public void validateWithFilter() {
TSSubQuery sub = getMetricForValidate();
sub.setFilters(Arrays.asList(TagVFilter.Builder()
.setFilter("*nari").setType("wildcard").setTagk("host").build()));
sub.validateAndSetQuery();
assertEquals("sys.cpu.0", sub.getMetric());
assertEquals(1, sub.getFilters().size());
assertTrue(sub.getFilters().get(0) instanceof TagVWildcardFilter);
assertEquals(0, sub.getTags().size());
assertEquals(Aggregators.SUM, sub.aggregator());
assertEquals(Aggregators.AVG, sub.downsampler());
assertEquals(300000, sub.downsampleInterval());
}
@Test
public void validateWithFilterViaTags() {
TSSubQuery sub = getMetricForValidate();
final Map<String, String> tags = new HashMap<String, String>();
tags.put("host", TagVWildcardFilter.FILTER_NAME + "(*nari)");
sub.setTags(tags);
sub.validateAndSetQuery();
assertEquals("sys.cpu.0", sub.getMetric());
assertEquals(1, sub.getFilters().size());
assertTrue(sub.getFilters().get(0) instanceof TagVWildcardFilter);
assertEquals("wildcard(*nari)", sub.getTags().get("host"));
assertEquals(Aggregators.SUM, sub.aggregator());
assertEquals(Aggregators.AVG, sub.downsampler());
assertEquals(300000, sub.downsampleInterval());
}
@Test
public void validateGroupByFilterMissingParensViaTags() {
TSSubQuery sub = getMetricForValidate();
final Map<String, String> tags = new HashMap<String, String>();
tags.put("host", TagVWildcardFilter.FILTER_NAME);
sub.setTags(tags);
sub.validateAndSetQuery();
assertEquals("sys.cpu.0", sub.getMetric());
assertEquals(1, sub.getFilters().size());
assertTrue(sub.getFilters().get(0) instanceof TagVLiteralOrFilter);
assertEquals(Aggregators.SUM, sub.aggregator());
assertEquals(Aggregators.AVG, sub.downsampler());
assertEquals(300000, sub.downsampleInterval());
}
@Test
public void validateWithGroupByFilter() {
TSSubQuery sub = getMetricForValidate();
sub.setFilters(Arrays.asList(TagVFilter.Builder()
.setFilter("*nari").setType("wildcard").setTagk("host")
.setGroupBy(true).build()));
sub.validateAndSetQuery();
assertEquals("sys.cpu.0", sub.getMetric());
assertEquals("wildcard(*nari)", sub.getTags().get("host"));
assertEquals(1, sub.getFilters().size());
assertTrue(sub.getFilters().get(0) instanceof TagVWildcardFilter);
assertEquals(Aggregators.SUM, sub.aggregator());
assertEquals(Aggregators.AVG, sub.downsampler());
assertEquals(300000, sub.downsampleInterval());
}
@Test
public void validateWithFilterAndGroupByFilter() {
TSSubQuery sub = getMetricForValidate();
final List<TagVFilter> filters = new ArrayList<TagVFilter>(1);
filters.add(new TagVWildcardFilter("colo", "lga*"));
sub.setFilters(filters);
Map<String, String> tags = new HashMap<String, String>();
tags.put("host", TagVWildcardFilter.FILTER_NAME + "(*nari)");
sub.setTags(tags);
sub.validateAndSetQuery();
assertEquals("sys.cpu.0", sub.getMetric());
assertEquals(TagVWildcardFilter.FILTER_NAME + "(*nari)",
sub.getTags().get("host"));
assertEquals(1, sub.getFilters().size());
assertEquals(Aggregators.SUM, sub.aggregator());
assertEquals(Aggregators.AVG, sub.downsampler());
assertEquals(300000, sub.downsampleInterval());
}
@Test
public void validateWithFilterAndGroupByFilterSameTag() {
TSSubQuery sub = getMetricForValidate();
final List<TagVFilter> filters = new ArrayList<TagVFilter>(1);
filters.add(new TagVWildcardFilter("host", "veti*"));
sub.setFilters(filters);
Map<String, String> tags = new HashMap<String, String>();
tags.put("host", TagVWildcardFilter.FILTER_NAME + "(*nari)");
sub.setTags(tags);
sub.validateAndSetQuery();
assertEquals("sys.cpu.0", sub.getMetric());
assertEquals(TagVWildcardFilter.FILTER_NAME + "(*nari)",
sub.getTags().get("host"));
assertEquals(1, sub.getFilters().size());
assertEquals(Aggregators.SUM, sub.aggregator());
assertEquals(Aggregators.AVG, sub.downsampler());
assertEquals(300000, sub.downsampleInterval());
}
@Test (expected = IllegalArgumentException.class)
public void validateWithDownsampleNone() {
TSSubQuery sub = getMetricForValidate();
sub.setDownsample("1m-none");
sub.validateAndSetQuery();
}
// NOTE: Each of the hash and equals tests should make sure that we the code
// doesn't change after validation.
@Test
public void testHashCodeandEqualsAggregator() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setAggregator("max");
final int has_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(has_b, sub1.hashCode());
final TSSubQuery sub2 = getBaseQuery();
sub2.setAggregator("max");
assertEquals(has_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test (expected = IllegalArgumentException.class)
public void testHashCodeandEqualsAggregatorNull() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setAggregator(null);
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
}
@Test (expected = IllegalArgumentException.class)
public void testHashCodeandEqualsAggregatorNonExistant() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setAggregator("nosuchagg");
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
}
@Test
public void testHashCodeandEqualsMetric() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setMetric("foo");
assertEquals(hash_a, sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_a, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
sub2.setMetric("foo");
assertEquals(hash_a, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test (expected = IllegalArgumentException.class)
public void testHashCodeandEqualsMetricNull() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setMetric(null);
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
}
@Test
public void testHashCodeandEqualsTSUIDs() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
List<String> tsuids = new ArrayList<String>(2);
tsuids.add("01010101");
tsuids.add("01010102");
sub1.setTsuids(tsuids);
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
List<String> tsuids2 = new ArrayList<String>(2);
tsuids2.add("01010101");
tsuids2.add("01010102");
sub2.setTsuids(tsuids2);
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsTSUIDsChange() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
List<String> tsuids = new ArrayList<String>(2);
tsuids.add("01010101");
tsuids.add("01010102");
sub1.setTsuids(tsuids);
tsuids.set(1, "01010103");
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
List<String> tsuids2 = new ArrayList<String>(2);
tsuids2.add("01010101");
tsuids2.add("01010103");
sub2.setTsuids(tsuids2);
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsTag() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
Map<String, String> tags = new HashMap<String, String>();
tags.put("host", "web02");
sub1.setTags(tags);
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
tags = new HashMap<String, String>();
tags.put("host", "web02");
sub2.setTags(tags);
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsTags() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
Map<String, String> tags = new HashMap<String, String>();
tags.put("host", "web02");
tags.put("foo", "bar");
sub1.setTags(tags);
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
tags = new HashMap<String, String>();
tags.put("host", "web02");
tags.put("foo", "bar");
sub2.setTags(tags);
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsTagsNull() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setTags(null);
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
sub2.setTags(null);
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsDownsampler() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setDownsample("1h-avg");
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
sub2.setDownsample("1h-avg");
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test (expected = IllegalArgumentException.class)
public void testHashCodeandEqualsDownsamplerInvalid() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setDownsample("bad ds");
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
}
@Test
public void testHashCodeandEqualsRate() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setRate(false);
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
sub2.setRate(false);
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsRateOptionsSameNew() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setRateOptions(new RateOptions(true, 1024, 16));
final int hash_b = sub1.hashCode();
assertTrue(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsRateOptionsNotCounter() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setRateOptions(new RateOptions(false, 1024, 16));
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
sub2.setRateOptions(new RateOptions(false, 1024, 16));
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsRateOptionsNewMax() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setRateOptions(new RateOptions(true, 768, 16));
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
sub2.setRateOptions(new RateOptions(true, 768, 16));
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsRateOptionsNewReset() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setRateOptions(new RateOptions(true, 1024, 32));
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
sub2.setRateOptions(new RateOptions(true, 1024, 32));
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsRateOptionsNull() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setRateOptions(null);
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
sub2.setRateOptions(null);
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testHashCodeandEqualsExplicitTags() {
final TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setExplicitTags(true);
final int hash_b = sub1.hashCode();
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
assertEquals(hash_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
sub2.setExplicitTags(true);
assertEquals(hash_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
@Test
public void testEqualsNull() {
final TSSubQuery sub1 = getBaseQuery();
assertFalse(sub1.equals(null));
}
@Test
public void testEqualsWrongType() {
final TSSubQuery sub1 = getBaseQuery();
assertFalse(sub1.equals(new String("Foobar")));
}
@Test
public void testEqualsSame() {
final TSSubQuery sub1 = getBaseQuery();
assertTrue(sub1.equals(sub1));
}
@Test
public void testHashCodeandEqualsFilter() {
TSSubQuery sub1 = getBaseQuery();
final int hash_a = sub1.hashCode();
sub1.setFilters(Arrays.asList(TagVFilter.Builder()
.setFilter("*nari").setType("wildcard").setTagk("host")
.setGroupBy(true).build()));
assertFalse(hash_a == sub1.hashCode());
sub1.validateAndSetQuery();
final int has_b = sub1.hashCode();
assertEquals(has_b, sub1.hashCode());
TSSubQuery sub2 = getBaseQuery();
sub2.setFilters(Arrays.asList(TagVFilter.Builder()
.setFilter("*nari").setType("wildcard").setTagk("host")
.setGroupBy(true).build()));
sub2.validateAndSetQuery();
assertEquals(has_b, sub2.hashCode());
assertEquals(sub1, sub2);
assertFalse(sub1 == sub2);
}
/** @return a sub query object with some defaults set for testing */
public static TSSubQuery getBaseQuery() {
TSSubQuery query = new TSSubQuery();
query.setAggregator("sum");
query.setMetric("foo");
HashMap<String, String> tags = new HashMap<String, String>(2);
tags.put("host", "web01");
tags.put("dc", "lax");
query.setTags(tags);
query.setRate(true);
query.setRateOptions(new RateOptions(true, 1024, 16));
return query;
}
/**
* Sets up an object with good, common values for testing the validation
* function with an "m" type query (no tsuids). Each test can "set" the
* method it wants to fool with and call .validateAndSetQuery()
* <b>Warning:</b> This method is also shared by {@link TestTSQuery} so be
* careful if you change any values
* @return A sub query object
*/
public static TSSubQuery getMetricForValidate() {
final TSSubQuery sub = new TSSubQuery();
sub.setAggregator("sum");
sub.setDownsample("5m-avg");
sub.setMetric("sys.cpu.0");
sub.setRate(false);
final HashMap<String, String> tags = new HashMap<String, String>();
tags.put("host", "*");
tags.put("dc", "lga");
sub.setTags(tags);
return sub;
}
}