// This file is part of OpenTSDB.
// Copyright (C) 2011-2012 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 java.lang.reflect.Field;
import java.util.ArrayList;
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.TagVLiteralOrFilter.TagVILiteralOrFilter;
import net.opentsdb.query.filter.TagVRegexFilter;
import net.opentsdb.query.filter.TagVWildcardFilter;
import net.opentsdb.storage.MockBase;
import net.opentsdb.uid.FailedToAssignUniqueIdException;
import net.opentsdb.uid.NoSuchUniqueId;
import net.opentsdb.uid.NoSuchUniqueName;
import net.opentsdb.uid.UniqueId;
import net.opentsdb.utils.Config;
import net.opentsdb.utils.Pair;
import org.hbase.async.Bytes;
import org.hbase.async.DeleteRequest;
import org.hbase.async.GetRequest;
import org.hbase.async.HBaseClient;
import org.hbase.async.KeyValue;
import org.hbase.async.PutRequest;
import org.hbase.async.Bytes.ByteMap;
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;
import com.stumbleupon.async.DeferredGroupException;
import static org.junit.Assert.assertArrayEquals;
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 static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.anyMapOf;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mock;
@PowerMockIgnore({"javax.management.*", "javax.xml.*",
"ch.qos.*", "org.slf4j.*",
"com.sum.*", "org.xml.*"})
@RunWith(PowerMockRunner.class)
@PrepareForTest({TSDB.class, Config.class, UniqueId.class, HBaseClient.class,
GetRequest.class, PutRequest.class, DeleteRequest.class, KeyValue.class,
Const.class})
public final class TestTags {
private TSDB tsdb;
private Config config;
private HBaseClient client;
private MockBase storage = null;
private UniqueId metrics = mock(UniqueId.class);
private UniqueId tag_names = mock(UniqueId.class);
private UniqueId tag_values = mock(UniqueId.class);
@Test
public void parseWithMetricWTag() {
final HashMap<String, String> tags = new HashMap<String, String>(1);
final String metric = Tags.parseWithMetric("sys.cpu.user{host=web01}", tags);
assertEquals("sys.cpu.user", metric);
assertEquals(1, tags.size());
assertEquals("web01", tags.get("host"));
}
@Test
public void parseWithMetricWTags() {
final HashMap<String, String> tags = new HashMap<String, String>(2);
final String metric = Tags.parseWithMetric("sys.cpu.user{host=web01,dc=lga}",
tags);
assertEquals("sys.cpu.user", metric);
assertEquals(2, tags.size());
assertEquals("web01", tags.get("host"));
assertEquals("lga", tags.get("dc"));
}
@Test
public void parseWithMetricMetricOnly() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
final String metric = Tags.parseWithMetric("sys.cpu.user", tags);
assertEquals("sys.cpu.user", metric);
assertEquals(0, tags.size());
}
@Test
public void parseWithMetricMetricEmptyCurlies() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
final String metric = Tags.parseWithMetric("sys.cpu.user{}", tags);
assertEquals("sys.cpu.user", metric);
assertEquals(0, tags.size());
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricNullMetric() {
final HashMap<String, String> tags = new HashMap<String, String>(1);
Tags.parseWithMetric("{host=}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricNullTagv() {
final HashMap<String, String> tags = new HashMap<String, String>(1);
Tags.parseWithMetric("sys.cpu.user{host=}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricNullTagk() {
final HashMap<String, String> tags = new HashMap<String, String>(1);
Tags.parseWithMetric("sys.cpu.user{=web01}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricNullTagv2() {
final HashMap<String, String> tags = new HashMap<String, String>(2);
Tags.parseWithMetric("sys.cpu.user{host=web01,dc=}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricNullTagk2() {
final HashMap<String, String> tags = new HashMap<String, String>(2);
Tags.parseWithMetric("sys.cpu.user{host=web01,=lga}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricNullTagv3() {
final HashMap<String, String> tags = new HashMap<String, String>(3);
Tags.parseWithMetric("sys.cpu.user{host=web01,dc=,=root}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricNullTagk3() {
final HashMap<String, String> tags = new HashMap<String, String>(3);
Tags.parseWithMetric("sys.cpu.user{host=web01,=lga,owner=}", tags);
}
@Test (expected = NullPointerException.class)
public void parseWithMetricNull() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
Tags.parseWithMetric(null, tags);
}
@Test
public void parseWithMetricEmpty() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
assertTrue(Tags.parseWithMetric("", tags).isEmpty());
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricMissingClosingCurly() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
Tags.parseWithMetric("sys.cpu.user{host=web01", tags);
}
// Maybe this one should throw an exception. Usually this will be used before
// a UID lookup so it will toss an exception then.
@Test
public void parseWithMetricMissingOpeningCurly() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
assertEquals("sys.cpu.user host=web01}",
Tags.parseWithMetric("sys.cpu.user host=web01}", tags));
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricMissingEquals() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
Tags.parseWithMetric("sys.cpu.user{hostweb01}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricMissingComma() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
Tags.parseWithMetric("sys.cpu.user{host=web01 dc=lga}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricTrailingComma() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
Tags.parseWithMetric("sys.cpu.user{host=web01,}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricForwardComma() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
Tags.parseWithMetric("sys.cpu.user{,host=web01}", tags);
}
@Test
public void parseWithMetricListMetricOnly() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(0);
final String metric = Tags.parseWithMetric("sys.cpu.user", tags);
assertEquals("sys.cpu.user", metric);
assertEquals(0, tags.size());
}
@Test
public void parseWithMetricListMetricEmptyCurlies() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(0);
final String metric = Tags.parseWithMetric("sys.cpu.user{}", tags);
assertEquals("sys.cpu.user", metric);
assertEquals(0, tags.size());
}
@Test
public void parseWithMetricListNullMetric() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(1);
final String metric = Tags.parseWithMetric("{host=}", tags);
assertNull(metric);
assertEquals(1, tags.size());
assertEquals("host", tags.get(0).getKey());
assertNull(tags.get(0).getValue());
}
@Test
public void parseWithMetricListNullTagv() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(1);
final String metric = Tags.parseWithMetric("sys.cpu.user{host=}", tags);
assertEquals("sys.cpu.user", metric);
assertEquals(1, tags.size());
assertEquals("host", tags.get(0).getKey());
assertNull(tags.get(0).getValue());
}
@Test
public void parseWithMetricListNullTagk() {
final List<Pair<String, String>> tags = new ArrayList<Pair<String, String>>(1);
final String metric = Tags.parseWithMetric("sys.cpu.user{=web01}", tags);
assertEquals("sys.cpu.user", metric);
assertEquals(1, tags.size());
assertNull(tags.get(0).getKey());
assertEquals("web01", tags.get(0).getValue());
}
@Test
public void parseWithMetricListWTag() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(1);
final String metric = Tags.parseWithMetric("sys.cpu.user{host=web01}", tags);
assertEquals("sys.cpu.user", metric);
assertEquals(1, tags.size());
assertEquals("host", tags.get(0).getKey());
assertEquals("web01", tags.get(0).getValue());
}
@Test
public void parseWithMetricListNullTagv2() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(2);
final String metric = Tags.parseWithMetric("sys.cpu.user{host=web01,dc=}",
tags);
assertEquals("sys.cpu.user", metric);
assertEquals(2, tags.size());
assertEquals("host", tags.get(0).getKey());
assertEquals("web01", tags.get(0).getValue());
assertEquals("dc", tags.get(1).getKey());
assertNull(tags.get(1).getValue());
}
@Test
public void parseWithMetricListNullTagk2() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(2);
final String metric = Tags.parseWithMetric("sys.cpu.user{host=web01,=lga}",
tags);
assertEquals("sys.cpu.user", metric);
assertEquals(2, tags.size());
assertEquals("host", tags.get(0).getKey());
assertEquals("web01", tags.get(0).getValue());
assertNull(tags.get(1).getKey());
assertEquals("lga", tags.get(1).getValue());
}
@Test
public void parseWithMetricListNullTagv3() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(3);
final String metric = Tags.parseWithMetric("sys.cpu.user{host=web01,dc=,=root}",
tags);
assertEquals("sys.cpu.user", metric);
assertEquals(3, tags.size());
assertEquals("host", tags.get(0).getKey());
assertEquals("web01", tags.get(0).getValue());
assertEquals("dc", tags.get(1).getKey());
assertNull(tags.get(1).getValue());
assertNull(tags.get(2).getKey());
assertEquals("root", tags.get(2).getValue());
}
@Test
public void parseWithMetricListNullTagk3() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(3);
final String metric = Tags.parseWithMetric("sys.cpu.user{host=web01,=lga,owner=}",
tags);
assertEquals("sys.cpu.user", metric);
assertEquals(3, tags.size());
assertEquals("host", tags.get(0).getKey());
assertEquals("web01", tags.get(0).getValue());
assertNull(tags.get(1).getKey());
assertEquals("lga", tags.get(1).getValue());
assertEquals("owner", tags.get(2).getKey());
assertNull(tags.get(2).getValue());
}
@Test (expected = NullPointerException.class)
public void parseWithMetricListNull() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(0);
Tags.parseWithMetric(null, tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricListEmpty() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(0);
Tags.parseWithMetric("", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricListMissingClosingCurly() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(0);
Tags.parseWithMetric("sys.cpu.user{host=web01", tags);
}
// Maybe this one should throw an exception. Usually this will be used before
// a UID lookup so it will toss an exception then.
@Test
public void parseWithMetricListMissingOpeningCurly() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(0);
assertEquals("sys.cpu.user host=web01}",
Tags.parseWithMetric("sys.cpu.user host=web01}", tags));
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricListMissingEquals() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(0);
Tags.parseWithMetric("sys.cpu.user{hostweb01}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricListMissingComma() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(0);
Tags.parseWithMetric("sys.cpu.user{host=web01 dc=lga}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricListTrailingComma() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(0);
Tags.parseWithMetric("sys.cpu.user{host=web01,}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricListForwardComma() {
final List<Pair<String, String>> tags =
new ArrayList<Pair<String, String>>(0);
Tags.parseWithMetric("sys.cpu.user{,host=web01}", tags);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricOnlyEquals() {
final HashMap<String, String> tags = new HashMap<String, String>(0);
Tags.parseWithMetric("{=}", tags);
}
@Test
public void parseWithMetricAndFilters() {
final List<TagVFilter> filters = new ArrayList<TagVFilter>();
String metric = Tags.parseWithMetricAndFilters("sys.cpu.user", filters);
assertEquals("sys.cpu.user", metric);
assertEquals(0, filters.size());
filters.clear();
metric = Tags.parseWithMetricAndFilters("sys.cpu.user{host=web01}", filters);
assertEquals("sys.cpu.user", metric);
assertEquals(1, filters.size());
assertEquals("host", filters.get(0).getTagk());
assertTrue(filters.get(0).isGroupBy());
assertTrue(filters.get(0) instanceof TagVLiteralOrFilter);
filters.clear();
metric = Tags.parseWithMetricAndFilters("sys.cpu.user{host=*}", filters);
assertEquals("sys.cpu.user", metric);
assertEquals(1, filters.size());
assertEquals("host", filters.get(0).getTagk());
assertTrue(filters.get(0).isGroupBy());
assertTrue(filters.get(0) instanceof TagVWildcardFilter);
filters.clear();
metric = Tags.parseWithMetricAndFilters("sys.cpu.user{host=web01}{}", filters);
assertEquals("sys.cpu.user", metric);
assertEquals(1, filters.size());
assertEquals("host", filters.get(0).getTagk());
assertTrue(filters.get(0).isGroupBy());
assertTrue(filters.get(0) instanceof TagVLiteralOrFilter);
filters.clear();
metric = Tags.parseWithMetricAndFilters(
"sys.cpu.user{host=*,owner=regexp(.*ob)}", filters);
assertEquals("sys.cpu.user", metric);
assertEquals(2, filters.size());
for (final TagVFilter filter : filters) {
if (filter instanceof TagVWildcardFilter) {
assertEquals("host", filter.getTagk());
} else if (filter instanceof TagVRegexFilter) {
assertEquals("owner", filter.getTagk());
}
assertTrue(filter.isGroupBy());
}
filters.clear();
metric = Tags.parseWithMetricAndFilters("sys.cpu.user{}{host=web01}", filters);
assertEquals("sys.cpu.user", metric);
assertEquals(1, filters.size());
assertEquals("host", filters.get(0).getTagk());
assertFalse(filters.get(0).isGroupBy());
assertTrue(filters.get(0) instanceof TagVLiteralOrFilter);
filters.clear();
metric = Tags.parseWithMetricAndFilters(
"sys.cpu.user{}{host=iliteral_or(web01|Web02)}", filters);
assertEquals("sys.cpu.user", metric);
assertEquals(1, filters.size());
assertEquals("host", filters.get(0).getTagk());
assertFalse(filters.get(0).isGroupBy());
assertTrue(filters.get(0) instanceof TagVILiteralOrFilter);
filters.clear();
metric = Tags.parseWithMetricAndFilters(
"sys.cpu.user{}{host=iliteral_or(web01|Web02),owner=*}", filters);
assertEquals("sys.cpu.user", metric);
assertEquals(2, filters.size());
for (final TagVFilter filter : filters) {
if (filter instanceof TagVWildcardFilter) {
assertEquals("owner", filter.getTagk());
} else if (filter instanceof TagVILiteralOrFilter) {
assertEquals("host", filter.getTagk());
}
assertFalse(filter.isGroupBy());
}
filters.clear();
metric = Tags.parseWithMetricAndFilters(
"sys.cpu.user{host=iliteral_or(web01|Web02)}{owner=*}", filters);
assertEquals("sys.cpu.user", metric);
System.out.println(filters);
assertEquals(2, filters.size());
for (final TagVFilter filter : filters) {
if (filter instanceof TagVWildcardFilter) {
assertEquals("owner", filter.getTagk());
assertFalse(filter.isGroupBy());
} else if (filter instanceof TagVILiteralOrFilter) {
assertEquals("host", filter.getTagk());
assertTrue(filter.isGroupBy());
}
}
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricAndFiltersMissingTrailingCurly() {
final List<TagVFilter> filters = new ArrayList<TagVFilter>();
Tags.parseWithMetricAndFilters("sys.cpu.user{}{host=web01", filters);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricAndFiltersNullString() {
final List<TagVFilter> filters = new ArrayList<TagVFilter>();
Tags.parseWithMetricAndFilters(null, filters);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricAndFiltersEmptyString() {
final List<TagVFilter> filters = new ArrayList<TagVFilter>();
Tags.parseWithMetricAndFilters("", filters);
}
@Test (expected = IllegalArgumentException.class)
public void parseWithMetricAndFiltersNullFilters() {
Tags.parseWithMetricAndFilters("sys.cpu.user{}{host=web01}", null);
}
@Test
public void parseSuccessful() {
final HashMap<String, String> tags = new HashMap<String, String>(2);
Tags.parse(tags, "foo=bar");
assertEquals(1, tags.size());
assertEquals("bar", tags.get("foo"));
Tags.parse(tags, "qux=baz");
assertEquals(2, tags.size());
assertEquals("bar", tags.get("foo"));
assertEquals("baz", tags.get("qux"));
}
@Test(expected=IllegalArgumentException.class)
public void parseNoEqualSign() {
Tags.parse(new HashMap<String, String>(1), "foo");
}
@Test(expected=IllegalArgumentException.class)
public void parseTooManyEqualSigns() {
Tags.parse(new HashMap<String, String>(1), "foo=bar=qux");
}
@Test(expected=IllegalArgumentException.class)
public void parseEmptyTagName() {
Tags.parse(new HashMap<String, String>(1), "=bar");
}
@Test(expected=IllegalArgumentException.class)
public void parseEmptyTagValue() {
Tags.parse(new HashMap<String, String>(1), "foo=");
}
@Test(expected=IllegalArgumentException.class)
public void parseDifferentValues() {
final HashMap<String, String> tags = new HashMap<String, String>(1);
Tags.parse(tags, "foo=bar");
assertEquals(1, tags.size());
assertEquals("bar", tags.get("foo"));
Tags.parse(tags, "foo=qux");
}
@Test
public void parseSameValues() {
final HashMap<String, String> tags = new HashMap<String, String>(1);
Tags.parse(tags, "foo=bar");
assertEquals(1, tags.size());
assertEquals("bar", tags.get("foo"));
Tags.parse(tags, "foo=bar");
assertEquals(1, tags.size());
assertEquals("bar", tags.get("foo"));
}
@Test
public void validateGoodString() {
Tags.validateString("test", "omg-TSDB/42._foo_");
}
@Test(expected=IllegalArgumentException.class)
public void validateNullString() {
Tags.validateString("test", null);
}
@Test(expected=IllegalArgumentException.class)
public void validateBadString() {
Tags.validateString("test", "this is a test!");
}
// parseLong
@Test
public void parseLongSimple() {
assertEquals(0, Tags.parseLong("0"));
assertEquals(0, Tags.parseLong("+0"));
assertEquals(0, Tags.parseLong("-0"));
assertEquals(1, Tags.parseLong("1"));
assertEquals(1, Tags.parseLong("+1"));
assertEquals(-1, Tags.parseLong("-1"));
assertEquals(4242, Tags.parseLong("4242"));
assertEquals(4242, Tags.parseLong("+4242"));
assertEquals(-4242, Tags.parseLong("-4242"));
}
@Test
public void parseLongMaxValue() {
assertEquals(Long.MAX_VALUE, Tags.parseLong(Long.toString(Long.MAX_VALUE)));
}
@Test
public void parseLongMinValue() {
assertEquals(Long.MIN_VALUE, Tags.parseLong(Long.toString(Long.MIN_VALUE)));
}
@Test(expected=NumberFormatException.class)
public void parseLongEmptyString() {
Tags.parseLong("");
}
@Test(expected=NumberFormatException.class)
public void parseLongMalformed() {
Tags.parseLong("42a51");
}
@Test(expected=NumberFormatException.class)
public void parseLongMalformedPlus() {
Tags.parseLong("+");
}
@Test(expected=NumberFormatException.class)
public void parseLongMalformedMinus() {
Tags.parseLong("-");
}
@Test(expected=NumberFormatException.class)
public void parseLongValueTooLarge() {
Tags.parseLong("18446744073709551616");
}
@Test(expected=NumberFormatException.class)
public void parseLongValueTooLargeSubtle() {
Tags.parseLong("9223372036854775808"); // MAX_VALUE + 1
}
@Test(expected=NumberFormatException.class)
public void parseLongValueTooSmallSubtle() {
Tags.parseLong("-9223372036854775809"); // MIN_VALUE - 1
}
@Test
public void resolveIdsAsync() throws Exception {
setupStorage();
setupResolveIds();
final List<byte[]> ids = new ArrayList<byte[]>(1);
ids.add(new byte[] { 0, 0, 1, 0, 0, 1 });
final HashMap<String, String> tags = Tags.resolveIdsAsync(tsdb, ids)
.joinUninterruptibly();
assertEquals("web01", tags.get("host"));
}
@Test (expected = NoSuchUniqueId.class)
public void resolveIdsAsyncNSUI() throws Exception {
setupStorage();
setupResolveIds();
final List<byte[]> ids = new ArrayList<byte[]>(1);
ids.add(new byte[] { 0, 0, 1, 0, 0, 2 });
Tags.resolveIdsAsync(tsdb, ids).joinUninterruptibly();
}
@Test
public void resolveIdsAsyncEmptyList() throws Exception {
setupStorage();
setupResolveIds();
final List<byte[]> ids = new ArrayList<byte[]>(0);
final HashMap<String, String> tags = Tags.resolveIdsAsync(tsdb, ids)
.joinUninterruptibly();
assertNotNull(tags);
assertEquals(0, tags.size());
}
@Test (expected = IllegalArgumentException.class)
public void resolveIdsAsyncWrongLength() throws Exception {
setupStorage();
setupResolveIds();
final List<byte[]> ids = new ArrayList<byte[]>(1);
ids.add(new byte[] { 0, 0, 1, 0, 0, 0, 2 });
Tags.resolveIdsAsync(tsdb, ids).joinUninterruptibly();
}
@Test
public void resolveOrCreateAllCreate() throws Exception {
setupStorage();
setupResolveAll();
final Map<String, String> tags = new HashMap<String, String>(1);
tags.put("host", "web01");
final List<byte[]> uids = Tags.resolveOrCreateAll(tsdb, tags);
assertEquals(1, uids.size());
assertArrayEquals(new byte[] { 0, 0, 1, 0, 0, 1}, uids.get(0));
}
@Test
public void resolveOrCreateTagkAllowed() throws Exception {
setupStorage();
setupResolveAll();
final Map<String, String> tags = new HashMap<String, String>(1);
tags.put("doesnotexist", "web01");
final List<byte[]> uids = Tags.resolveOrCreateAll(tsdb, tags);
assertEquals(1, uids.size());
assertArrayEquals(new byte[] { 0, 0, 3, 0, 0, 1}, uids.get(0));
}
@Test
public void resolveOrCreateTagkNotAllowedGood() throws Exception {
setupStorage();
config.overrideConfig("tsd.core.auto_create_tagks", "false");
setupResolveAll();
final Map<String, String> tags = new HashMap<String, String>(1);
tags.put("pop", "web01");
final List<byte[]> uids = Tags.resolveOrCreateAll(tsdb, tags);
assertEquals(1, uids.size());
assertArrayEquals(new byte[] { 0, 0, 2, 0, 0, 1}, uids.get(0));
}
@Test (expected = NoSuchUniqueName.class)
public void resolveOrCreateTagkNotAllowedBlocked() throws Exception {
setupStorage();
config.overrideConfig("tsd.core.auto_create_tagks", "false");
setupResolveAll();
final Map<String, String> tags = new HashMap<String, String>(1);
tags.put("nonesuch", "web01");
Tags.resolveOrCreateAll(tsdb, tags);
}
@Test
public void resolveOrCreateTagvAllowed() throws Exception {
setupStorage();
setupResolveAll();
final Map<String, String> tags = new HashMap<String, String>(1);
tags.put("host", "nohost");
final List<byte[]> uids = Tags.resolveOrCreateAll(tsdb, tags);
assertEquals(1, uids.size());
assertArrayEquals(new byte[] { 0, 0, 1, 0, 0, 3}, uids.get(0));
}
@Test
public void resolveOrCreateTagvNotAllowedGood() throws Exception {
setupStorage();
config.overrideConfig("tsd.core.auto_create_tagvs", "false");
setupResolveAll();
final Map<String, String> tags = new HashMap<String, String>(1);
tags.put("host", "web02");
final List<byte[]> uids = Tags.resolveOrCreateAll(tsdb, tags);
assertEquals(1, uids.size());
assertArrayEquals(new byte[] { 0, 0, 1, 0, 0, 2}, uids.get(0));
}
@Test (expected = NoSuchUniqueName.class)
public void resolveOrCreateTagvNotAllowedBlocked() throws Exception {
setupStorage();
config.overrideConfig("tsd.core.auto_create_tagvs", "false");
setupResolveAll();
final Map<String, String> tags = new HashMap<String, String>(1);
tags.put("host", "invalidhost");
Tags.resolveOrCreateAll(tsdb, tags);
}
@Test
public void resolveOrCreateAllAsync() throws Exception {
setupStorage();
setupResolveAll();
final Map<String, String> tags = new HashMap<String, String>(1);
tags.put("host", "nohost");
final List<byte[]> uids = Tags.resolveOrCreateAllAsync(tsdb, "metric", tags).join();
assertEquals(1, uids.size());
assertArrayEquals(new byte[] { 0, 0, 1, 0, 0, 3}, uids.get(0));
}
@Test (expected = DeferredGroupException.class)
public void resolveOrCreateAllAsyncFilterBlocked() throws Exception {
setupStorage();
setupResolveAll();
when(tag_names.getOrCreateIdAsync(eq("host"), anyString(),
anyMapOf(String.class, String.class)))
.thenReturn(Deferred.<byte[]>fromError(new FailedToAssignUniqueIdException(
"tagk", "host", 0, "Blocked by UID filter.")));
final Map<String, String> tags = new HashMap<String, String>(1);
tags.put("host", "nohost");
Tags.resolveOrCreateAllAsync(tsdb, "metric", tags).join();
}
// PRIVATE helpers to setup unit tests
private void setupStorage() throws Exception {
config = new Config(false);
client = mock(HBaseClient.class);
tsdb = new TSDB(config);
storage = new MockBase(tsdb, client, true, true, true, true);
// replace the "real" field objects with mocks
Field cl = tsdb.getClass().getDeclaredField("client");
cl.setAccessible(true);
cl.set(tsdb, client);
Field met = tsdb.getClass().getDeclaredField("metrics");
met.setAccessible(true);
met.set(tsdb, metrics);
Field tagk = tsdb.getClass().getDeclaredField("tag_names");
tagk.setAccessible(true);
tagk.set(tsdb, tag_names);
Field tagv = tsdb.getClass().getDeclaredField("tag_values");
tagv.setAccessible(true);
tagv.set(tsdb, tag_values);
when(metrics.width()).thenReturn((short)3);
when(tag_names.width()).thenReturn((short)3);
when(tag_values.width()).thenReturn((short)3);
}
private void setupResolveIds() throws Exception {
when(tag_names.getNameAsync(new byte[] { 0, 0, 1 }))
.thenReturn(Deferred.fromResult("host"));
when(tag_names.getNameAsync(new byte[] { 0, 0, 2 }))
.thenThrow(new NoSuchUniqueId("tagk", new byte[] { 0, 0, 2 }));
when(tag_values.getNameAsync(new byte[] { 0, 0, 1 }))
.thenReturn(Deferred.fromResult("web01"));
when(tag_values.getNameAsync(new byte[] { 0, 0, 2 }))
.thenThrow(new NoSuchUniqueId("tagv", new byte[] { 0, 0, 2 }));
}
private void setupResolveAll() throws Exception {
when(tag_names.getOrCreateId(eq("host")))
.thenReturn(new byte[] { 0, 0, 1 });
when(tag_names.getOrCreateIdAsync(eq("host"), anyString(),
anyMapOf(String.class, String.class)))
.thenReturn(Deferred.fromResult(new byte[] { 0, 0, 1 }));
when(tag_names.getOrCreateId(eq("doesnotexist")))
.thenReturn(new byte[] { 0, 0, 3 });
when(tag_names.getOrCreateIdAsync(eq("doesnotexist"), anyString(),
anyMapOf(String.class, String.class)))
.thenReturn(Deferred.fromResult(new byte[] { 0, 0, 3 }));
when(tag_names.getId("pop")).thenReturn(new byte[] { 0, 0, 2 });
when(tag_names.getId("nonesuch"))
.thenThrow(new NoSuchUniqueName("tagv", "nonesuch"));
when(tag_values.getOrCreateId(eq("web01")))
.thenReturn(new byte[] { 0, 0, 1 });
when(tag_values.getOrCreateIdAsync(eq("web01"), anyString(),
anyMapOf(String.class, String.class)))
.thenReturn(Deferred.fromResult(new byte[] { 0, 0, 1 }));
when(tag_values.getOrCreateId(eq("nohost")))
.thenReturn(new byte[] { 0, 0, 3 });
when(tag_values.getOrCreateIdAsync(eq("nohost"), anyString(),
anyMapOf(String.class, String.class)))
.thenReturn(Deferred.fromResult(new byte[] { 0, 0, 3 }));
when(tag_values.getId("web02")).thenReturn(new byte[] { 0, 0, 2 });
when(tag_values.getId("invalidhost"))
.thenThrow(new NoSuchUniqueName("tagk", "invalidhost"));
}
@Test
public void getTagUids() throws Exception {
byte[] row = new byte[] { 0, 0, 1, 0x50, (byte)0xE2, 0x27, 0,
0, 0, 1, 0, 0, 2};
ByteMap<byte[]> uids = Tags.getTagUids(row);
assertEquals(1, uids.size());
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 1 }, uids.firstKey()));
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 2 }, uids.firstEntry()
.getValue()));
row = new byte[] { 0, 0, 1, 0x50, (byte)0xE2, 0x27, 0,
0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4};
uids = Tags.getTagUids(row);
assertEquals(2, uids.size());
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 1 }, uids.firstKey()));
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 2 }, uids.firstEntry()
.getValue()));
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 3 }, uids.lastKey()));
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 4 }, uids.lastEntry()
.getValue()));
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
row = new byte[] { 1, 0, 0, 1, 0x50, (byte)0xE2, 0x27, 0,
0, 0, 1, 0, 0, 2};
uids = Tags.getTagUids(row);
assertEquals(1, uids.size());
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 1 }, uids.firstKey()));
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 2 }, uids.firstEntry()
.getValue()));
row = new byte[] { 1, 0, 0, 1, 0x50, (byte)0xE2, 0x27, 0,
0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4};
uids = Tags.getTagUids(row);
assertEquals(2, uids.size());
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 1 }, uids.firstKey()));
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 2 }, uids.firstEntry()
.getValue()));
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 3 }, uids.lastKey()));
assertEquals(0, Bytes.memcmp(new byte[] { 0, 0, 4 }, uids.lastEntry()
.getValue()));
}
@Test (expected = ArrayIndexOutOfBoundsException.class)
public void getTagUidsMissingTagV() throws Exception {
byte[] row = new byte[] { 0, 0, 1, 0x50, (byte)0xE2, 0x27, 0, 0, 0, 1 };
Tags.getTagUids(row);
}
@Test (expected = ArrayIndexOutOfBoundsException.class)
public void getTagUidsMissingTagVSalted() throws Exception {
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
byte[] row = new byte[] { 1, 0, 0, 1, 0x50, (byte)0xE2, 0x27, 0, 0, 0, 1 };
Tags.getTagUids(row);
}
@Test
public void getTagUidsMissingTags() throws Exception {
byte[] row = new byte[] { 0, 0, 1, 0x50, (byte)0xE2, 0x27, 0 };
ByteMap<byte[]> uids = Tags.getTagUids(row);
assertEquals(0, uids.size());
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
row = new byte[] { 1, 0, 0, 1, 0x50, (byte)0xE2, 0x27, 0 };
uids = Tags.getTagUids(row);
assertEquals(0, uids.size());
}
@Test (expected = NullPointerException.class)
public void getTagUidsNullRow() throws Exception {
Tags.getTagUids(null);
}
@Test
public void getTagUidsEmptyRow() throws Exception {
final ByteMap<byte[]> uids = Tags.getTagUids(new byte[] {});
assertEquals(0, uids.size());
}
@Test
public void setAllowSpecialChars() throws Exception {
assertFalse(Tags.isAllowSpecialChars('!'));
Tags.setAllowSpecialChars(null);
assertFalse(Tags.isAllowSpecialChars('!'));
Tags.setAllowSpecialChars("");
assertFalse(Tags.isAllowSpecialChars('!'));
Tags.setAllowSpecialChars("!)(%");
assertTrue(Tags.isAllowSpecialChars('!'));
assertTrue(Tags.isAllowSpecialChars('('));
assertTrue(Tags.isAllowSpecialChars('%'));
}
}