/* * Copyright 2016 KairosDB 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.kairosdb.datastore; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.SetMultimap; import com.google.common.collect.TreeMultimap; import org.junit.Test; import org.kairosdb.core.datapoints.LongDataPoint; import org.kairosdb.core.datastore.DataPointGroup; import org.kairosdb.core.datastore.DatastoreQuery; import org.kairosdb.core.datastore.KairosDatastore; import org.kairosdb.core.datastore.QueryMetric; import org.kairosdb.core.exception.DatastoreException; import org.kairosdb.core.groupby.TagGroupBy; import java.util.*; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; public abstract class DatastoreTestHelper { protected static KairosDatastore s_datastore; protected static final List<String> metricNames = new ArrayList<>(); private static long s_startTime; private static String s_unicodeNameWithSpace = "你好 means hello"; private static String s_unicodeName = "你好"; private static List<String> listFromIterable(Iterable<String> iterable) { List<String> ret = new ArrayList<>(); for (String s : iterable) { ret.add(s); } return (ret); } private static SetMultimap<String, String> extractTags(DataPointGroup dpGroup) { SetMultimap<String, String> resp = TreeMultimap.create(); for (String tag : dpGroup.getTagNames()) { for (String value : dpGroup.getTagValues(tag)) { resp.put(tag, value); } } return (resp); } /** * Must be called from implementing class */ protected static void loadData() throws DatastoreException { metricNames.add("metric1"); ImmutableSortedMap<String, String> tags; String metricName = "metric1"; tags = ImmutableSortedMap.<String, String>naturalOrder() .put("host", "A") .put("client", "foo") .put("month", "April") .build(); s_startTime = System.currentTimeMillis(); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime, 1)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 1000, 2)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 2000, 3)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 3000, 4)); tags = ImmutableSortedMap.<String, String>naturalOrder() .put("host", "B") .put("client", "foo") .put("month", "April") .build(); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime, 5)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 1000, 6)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 2000, 7)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 3000, 8)); tags = ImmutableSortedMap.<String, String>naturalOrder() .put("host", "A") .put("client", "bar") .put("month", "April") .build(); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime, 9)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 1000, 10)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 2000, 11)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 3000, 12)); metricNames.add("metric2"); metricName = "metric2"; tags = ImmutableSortedMap.<String, String>naturalOrder() .put("host", "B") .put("client", "bar") .put("month", "April") .build(); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime, 13)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 1000, 14)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 2000, 15)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime + 3000, 16)); metricNames.add("duplicates"); metricName = "duplicates"; tags = ImmutableSortedMap.<String, String>naturalOrder() .put("host", "A") .build(); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime, 4)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime, 42)); //Testing pre 1970 data points with negative values metricNames.add("old_data"); metricName = "old_data"; tags = ImmutableSortedMap.<String, String>naturalOrder() .put("host", "A").build(); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(-2000000000L, 80)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(-1000000000L, 40)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(-100L, 20)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(0L, 3)); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(2000000000L, 33)); //Adding a metric with unicode and spaces metricNames.add(s_unicodeNameWithSpace); metricName = s_unicodeNameWithSpace; tags = ImmutableSortedMap.<String, String>naturalOrder() .put("host", s_unicodeName) .put("space", "space is cool").build(); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime, 42)); //Data that will be deleted in test metricName = "delete_me"; metricNames.add(metricName); tags = ImmutableSortedMap.<String, String>naturalOrder() .put("ghost", "tag").build(); s_datastore.putDataPoint(metricName, tags, new LongDataPoint(s_startTime, 50)); } @Test public void test_getMetricNames() throws DatastoreException { List<String> metrics = listFromIterable(s_datastore.getMetricNames()); assertThat(metrics, hasItem("metric1")); assertThat(metrics, hasItem("metric2")); assertThat(metrics, hasItem("duplicates")); assertThat(metrics, hasItem("old_data")); } @Test public void test_getTagNames() throws DatastoreException { List<String> metrics = listFromIterable(s_datastore.getTagNames()); assertThat(metrics, hasItem("host")); assertThat(metrics, hasItem("client")); assertThat(metrics, hasItem("month")); } @Test public void test_getTagValues() throws DatastoreException { List<String> metrics = listFromIterable(s_datastore.getTagValues()); assertThat(metrics, hasItem("A")); assertThat(metrics, hasItem("B")); assertThat(metrics, hasItem("foo")); assertThat(metrics, hasItem("bar")); assertThat(metrics, hasItem("April")); } @Test public void test_queryDatabase_noTags() throws DatastoreException { Map<String, String> tags = new TreeMap<>(); QueryMetric query = new QueryMetric(s_startTime, 0, "metric1"); query.setEndTime(s_startTime + 3000); query.setTags(tags); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), equalTo(1)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is("metric1")); SetMultimap<String, String> resTags = extractTags(dpg); assertThat(resTags.size(), is(5)); SetMultimap<String, String> expectedTags = TreeMultimap.create(); expectedTags.put("host", "A"); expectedTags.put("host", "B"); expectedTags.put("client", "foo"); expectedTags.put("client", "bar"); expectedTags.put("month", "April"); assertThat(resTags, is(expectedTags)); assertValues(dpg, 1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12); } finally { dq.close(); } } @Test public void test_queryDatabase_withTags() throws DatastoreException { Map<String, String> tags = new TreeMap<>(); tags.put("client", "foo"); QueryMetric query = new QueryMetric(s_startTime, 0, "metric1"); query.setEndTime(s_startTime + 3000); query.setTags(tags); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), is(1)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is("metric1")); SetMultimap<String, String> resTags = extractTags(dpg); assertEquals(4, resTags.size()); SetMultimap<String, String> expectedTags = TreeMultimap.create(); expectedTags.put("host", "A"); expectedTags.put("host", "B"); expectedTags.put("client", "foo"); expectedTags.put("month", "April"); assertThat(resTags, is(expectedTags)); assertValues(dpg, 1, 5, 2, 6, 3, 7, 4, 8); } finally { dq.close(); } } @Test public void test_queryDatabase_withTagGroupBy() throws DatastoreException { Map<String, String> tags = new TreeMap<>(); QueryMetric query = new QueryMetric(s_startTime, 0, "metric1"); query.addGroupBy(new TagGroupBy(Collections.singletonList("host"))); query.setEndTime(s_startTime + 3000); query.setTags(tags); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), is(2)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is("metric1")); SetMultimap<String, String> resTags = extractTags(dpg); SetMultimap<String, String> expectedTags = TreeMultimap.create(); expectedTags.put("host", "A"); expectedTags.put("client", "foo"); expectedTags.put("client", "bar"); expectedTags.put("month", "April"); assertThat(resTags, equalTo(expectedTags)); assertValues(dpg, 1, 9, 2, 10, 3, 11, 4, 12); dpg = results.get(1); assertThat(dpg.getName(), is("metric1")); resTags = extractTags(dpg); expectedTags = TreeMultimap.create(); expectedTags.put("host", "B"); expectedTags.put("client", "foo"); expectedTags.put("month", "April"); assertThat(resTags, equalTo(expectedTags)); assertValues(dpg, 5, 6, 7, 8); } finally { dq.close(); } } @Test public void test_queryDatabase_withMultipleTagGroupBy() throws DatastoreException { Map<String, String> tags = new TreeMap<>(); QueryMetric query = new QueryMetric(s_startTime, 0, "metric1"); query.addGroupBy(new TagGroupBy("host", "client")); query.setEndTime(s_startTime + 3000); query.setTags(tags); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), is(3)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is("metric1")); SetMultimap<String, String> resTags = extractTags(dpg); assertThat(resTags.keySet().size(), is(3)); SetMultimap<String, String> expectedTags = TreeMultimap.create(); expectedTags.put("host", "A"); expectedTags.put("client", "bar"); expectedTags.put("month", "April"); assertThat(resTags, equalTo(expectedTags)); assertValues(dpg, 9, 10, 11, 12); dpg = results.get(1); assertThat(dpg.getName(), is("metric1")); resTags = extractTags(dpg); assertThat(resTags.keySet().size(), is(3)); expectedTags = TreeMultimap.create(); expectedTags.put("host", "A"); expectedTags.put("client", "foo"); expectedTags.put("month", "April"); assertThat(resTags, equalTo(expectedTags)); assertValues(dpg, 1, 2, 3, 4); dpg = results.get(2); assertThat(dpg.getName(), is("metric1")); resTags = extractTags(dpg); assertThat(resTags.keySet().size(), is(3)); expectedTags = TreeMultimap.create(); expectedTags.put("host", "B"); expectedTags.put("client", "foo"); expectedTags.put("month", "April"); assertThat(resTags, equalTo(expectedTags)); assertValues(dpg, 5, 6, 7, 8); } finally { dq.close(); } } @Test public void test_queryDatabase_withGroupBy_nonMatchingTag() throws DatastoreException { Map<String, String> tags = new TreeMap<>(); QueryMetric query = new QueryMetric(s_startTime, 0, "metric1"); query.addGroupBy(new TagGroupBy("bogus")); query.setEndTime(s_startTime + 3000); query.setTags(tags); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), is(1)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is("metric1")); SetMultimap<String, String> resTags = extractTags(dpg); assertThat(resTags.keySet().size(), is(3)); SetMultimap<String, String> expectedTags = TreeMultimap.create(); expectedTags.put("host", "A"); expectedTags.put("host", "B"); expectedTags.put("client", "foo"); expectedTags.put("client", "bar"); expectedTags.put("month", "April"); assertThat(resTags, is(expectedTags)); assertValues(dpg, 1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12); } finally { dq.close(); } } @Test public void test_queryWithMultipleTagsFilter() throws DatastoreException { Map<String, String> tags = new TreeMap<>(); tags.put("host", "A"); tags.put("client", "bar"); QueryMetric query = new QueryMetric(s_startTime, 0, "metric1"); query.addGroupBy(new TagGroupBy(Collections.singletonList("host"))); query.setEndTime(s_startTime + 3000); query.setTags(tags); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), is(1)); assertValues(results.get(0), 9, 10, 11, 12); } finally { dq.close(); } } @Test public void test_queryWithMultipleHostTags() throws DatastoreException { SetMultimap<String, String> tags = HashMultimap.create(); QueryMetric query = new QueryMetric(s_startTime, 0, "metric1"); query.setEndTime(s_startTime + 3000); tags.put("host", "A"); tags.put("host", "B"); query.setTags(tags); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), equalTo(1)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is("metric1")); SetMultimap<String, String> resTags = extractTags(dpg); assertThat(resTags.size(), is(5)); SetMultimap<String, String> expectedTags = TreeMultimap.create(); expectedTags.put("host", "A"); expectedTags.put("host", "B"); expectedTags.put("client", "foo"); expectedTags.put("client", "bar"); expectedTags.put("month", "April"); assertThat(resTags, is(expectedTags)); assertValues(dpg, 1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12); } finally { dq.close(); } } @Test public void test_duplicateDataPoints() throws DatastoreException { SetMultimap<String, String> tags = HashMultimap.create(); QueryMetric query = new QueryMetric(s_startTime, 0, "duplicates"); query.setEndTime(s_startTime + 3000); query.setTags(tags); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), equalTo(1)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is("duplicates")); SetMultimap<String, String> resTags = extractTags(dpg); assertThat(resTags.size(), is(1)); SetMultimap<String, String> expectedTags = TreeMultimap.create(); expectedTags.put("host", "A"); assertThat(resTags, is(expectedTags)); assertValues(dpg, 42); } finally { dq.close(); } } @Test public void test_queryDatabase_noResults() throws DatastoreException { Map<String, String> tags = new TreeMap<>(); QueryMetric query = new QueryMetric(500, 0, "metric1"); query.setEndTime(1000); query.setTags(tags); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), equalTo(1)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is("metric1")); assertFalse(dpg.hasNext()); } finally { dq.close(); } } @Test public void test_queryNegativeAndPositiveTime() throws DatastoreException { QueryMetric query = new QueryMetric(-2000000000L, 0, "old_data"); query.setEndTime(2000000000L); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), equalTo(1)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is("old_data")); SetMultimap<String, String> resTags = extractTags(dpg); assertThat(resTags.size(), is(1)); SetMultimap<String, String> expectedTags = TreeMultimap.create(); expectedTags.put("host", "A"); assertThat(resTags, is(expectedTags)); assertValues(dpg, 80, 40, 20, 3, 33); } finally { dq.close(); } } @Test public void test_queryNegativeTime() throws DatastoreException { QueryMetric query = new QueryMetric(-2000000000L, 0, "old_data"); query.setEndTime(-1L); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), equalTo(1)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is("old_data")); SetMultimap<String, String> resTags = extractTags(dpg); assertThat(resTags.size(), is(1)); SetMultimap<String, String> expectedTags = TreeMultimap.create(); expectedTags.put("host", "A"); assertThat(resTags, is(expectedTags)); assertValues(dpg, 80, 40, 20); } finally { dq.close(); } } @Test public void test_queryWithUnicode() throws DatastoreException { SetMultimap<String, String> tags = HashMultimap.create(); QueryMetric query = new QueryMetric(s_startTime, 0, s_unicodeNameWithSpace); query.setEndTime(s_startTime + 3000); tags.put("host", s_unicodeName); query.setTags(tags); DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), equalTo(1)); DataPointGroup dpg = results.get(0); assertThat(dpg.getName(), is(s_unicodeNameWithSpace)); SetMultimap<String, String> resTags = extractTags(dpg); assertThat(resTags.size(), is(2)); SetMultimap<String, String> expectedTags = TreeMultimap.create(); expectedTags.put("host", s_unicodeName); expectedTags.put("space", "space is cool"); assertThat(resTags, is(expectedTags)); assertValues(dpg, 42); } finally { dq.close(); } } @Test public void test_notReturningTagsForEmptyData() throws DatastoreException, InterruptedException { QueryMetric query = new QueryMetric(s_startTime - 1, 0, "delete_me"); query.setEndTime(s_startTime + 1); s_datastore.delete(query); Thread.sleep(1500); //Now query for the data DatastoreQuery dq = s_datastore.createQuery(query); try { List<DataPointGroup> results = dq.execute(); assertThat(results.size(), equalTo(1)); DataPointGroup dpg = results.get(0); SetMultimap<String, String> resTags = extractTags(dpg); assertThat(resTags.size(), is(0)); assertThat(dpg.hasNext(), is(false)); } finally { dq.close(); } } private void assertValues(DataPointGroup group, long... values) { for (long expected : values) { assertThat(group.hasNext(), is(true)); long actual = group.next().getLongValue(); assertThat(actual, is(expected)); } assertThat(group.hasNext(), is(false)); } }