// 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.tsd;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mock;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.List;
import net.opentsdb.core.DataPoints;
import net.opentsdb.core.Query;
import net.opentsdb.core.TSDB;
import net.opentsdb.core.TSQuery;
import net.opentsdb.core.TSSubQuery;
import net.opentsdb.query.expression.ExpressionTree;
import net.opentsdb.query.filter.TagVLiteralOrFilter;
import net.opentsdb.query.filter.TagVRegexFilter;
import net.opentsdb.query.filter.TagVWildcardFilter;
import net.opentsdb.storage.MockDataPoints;
import net.opentsdb.utils.Config;
import net.opentsdb.utils.DateTime;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import net.opentsdb.uid.NoSuchUniqueName;
import com.stumbleupon.async.Deferred;
import com.stumbleupon.async.DeferredGroupException;
/**
* Unit tests for the Query RPC class that handles parsing user queries for
* timeseries data and returning that data
* <b>Note:</b> Testing query validation and such should be done in the
* core.TestTSQuery and TestTSSubQuery classes
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ TSDB.class, Config.class, HttpQuery.class, Query.class,
Deferred.class, TSQuery.class, DateTime.class, DeferredGroupException.class })
public final class TestQueryRpc {
private TSDB tsdb = null;
private QueryRpc rpc;
private Query empty_query = mock(Query.class);
private Query query_result;
private List<ExpressionTree> expressions;
private static final Method parseQuery;
static {
try {
parseQuery = QueryRpc.class.getDeclaredMethod("parseQuery",
TSDB.class, HttpQuery.class, List.class);
parseQuery.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException("Failed in static initializer", e);
}
}
@Before
public void before() throws Exception {
tsdb = NettyMocks.getMockedHTTPTSDB();
empty_query = mock(Query.class);
query_result = mock(Query.class);
rpc = new QueryRpc();
expressions = null;
when(tsdb.newQuery()).thenReturn(query_result);
when(empty_query.run()).thenReturn(new DataPoints[0]);
when(query_result.configureFromQuery((TSQuery)any(), anyInt()))
.thenReturn(Deferred.fromResult(null));
when(query_result.runAsync())
.thenReturn(Deferred.fromResult(new DataPoints[0]));
}
@Test
public void parseQueryMType() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
assertNotNull(tsq);
assertEquals("1h-ago", tsq.getStart());
assertNotNull(tsq.getQueries());
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub);
assertEquals("sum", sub.getAggregator());
assertEquals("sys.cpu.0", sub.getMetric());
}
@Test
public void parseQueryMTypeWEnd() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&end=5m-ago&m=sum:sys.cpu.0");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
assertEquals("5m-ago", tsq.getEnd());
}
@Test
public void parseQuery2MType() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0&m=avg:sys.cpu.1");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
assertNotNull(tsq.getQueries());
assertEquals(2, tsq.getQueries().size());
TSSubQuery sub1 = tsq.getQueries().get(0);
assertNotNull(sub1);
assertEquals("sum", sub1.getAggregator());
assertEquals("sys.cpu.0", sub1.getMetric());
TSSubQuery sub2 = tsq.getQueries().get(1);
assertNotNull(sub2);
assertEquals("avg", sub2.getAggregator());
assertEquals("sys.cpu.1", sub2.getMetric());
}
@Test
public void parseQueryMTypeWRate() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:rate:sys.cpu.0");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
assertTrue(sub.getRate());
}
@Test
public void parseQueryMTypeWDS() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:1h-avg:sys.cpu.0");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
assertEquals("1h-avg", sub.getDownsample());
}
@Test
public void parseQueryMTypeWDSAndFill() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:1h-avg-lerp:sys.cpu.0");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
assertEquals("1h-avg-lerp", sub.getDownsample());
}
@Test
public void parseQueryMTypeWRateAndDS() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:1h-avg:rate:sys.cpu.0");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
assertTrue(sub.getRate());
assertEquals("1h-avg", sub.getDownsample());
}
@Test
public void parseQueryMTypeWTag() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{host=web01}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub.getTags());
assertEquals("literal_or(web01)", sub.getTags().get("host"));
}
@Test
public void parseQueryMTypeWGroupByRegex() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{host=" +
TagVRegexFilter.FILTER_NAME + "(something(foo|bar))}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
sub.validateAndSetQuery();
assertEquals(1, sub.getFilters().size());
assertTrue(sub.getFilters().get(0) instanceof TagVRegexFilter);
}
@Test
public void parseQueryMTypeWGroupByWildcardExplicit() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{host=" +
TagVWildcardFilter.FILTER_NAME + "(*quirm)}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
sub.validateAndSetQuery();
assertEquals(1, sub.getFilters().size());
assertTrue(sub.getFilters().get(0) instanceof TagVWildcardFilter);
}
@Test
public void parseQueryMTypeWGroupByWildcardImplicit() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{host=*quirm}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
sub.validateAndSetQuery();
assertEquals(1, sub.getFilters().size());
assertTrue(sub.getFilters().get(0) instanceof TagVWildcardFilter);
}
@Test
public void parseQueryMTypeWWildcardFilterExplicit() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{}{host=wildcard(*quirm)}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
sub.validateAndSetQuery();
assertEquals(1, sub.getFilters().size());
assertTrue(sub.getFilters().get(0) instanceof TagVWildcardFilter);
}
@Test
public void parseQueryMTypeWWildcardFilterImplicit() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{}{host=*quirm}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
sub.validateAndSetQuery();
assertEquals(1, sub.getFilters().size());
assertTrue(sub.getFilters().get(0) instanceof TagVWildcardFilter);
}
@Test
public void parseQueryMTypeWGroupByAndWildcardFilterExplicit() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{colo=lga}{host=wildcard(*quirm)}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
sub.validateAndSetQuery();
assertTrue(sub.getFilters().get(0) instanceof TagVWildcardFilter);
assertTrue(sub.getFilters().get(1) instanceof TagVLiteralOrFilter);
}
@Test
public void parseQueryMTypeWGroupByAndWildcardFilterSameTagK() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{host=quirm|tsort}"
+ "{host=wildcard(*quirm)}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
sub.validateAndSetQuery();
assertTrue(sub.getFilters().get(0) instanceof TagVWildcardFilter);
assertTrue(sub.getFilters().get(1) instanceof TagVLiteralOrFilter);
}
@Test
public void parseQueryMTypeWGroupByFilterAndWildcardFilterSameTagK()
throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{host=wildcard(*tsort)}"
+ "{host=wildcard(*quirm)}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
sub.validateAndSetQuery();
assertEquals(2, sub.getFilters().size());
assertTrue(sub.getFilters().get(0) instanceof TagVWildcardFilter);
assertTrue(sub.getFilters().get(1) instanceof TagVWildcardFilter);
}
@Test (expected = IllegalArgumentException.class)
public void parseQueryMTypeWGroupByFilterMissingClose() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{host=wildcard(*tsort)}"
+ "{host=wildcard(*quirm)");
parseQuery.invoke(rpc, tsdb, query, expressions);
}
@Test (expected = IllegalArgumentException.class)
public void parseQueryMTypeWGroupByFilterMissingEquals() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{host=wildcard(*tsort)}"
+ "{hostwildcard(*quirm)}");
parseQuery.invoke(rpc, tsdb, query, expressions);
}
@Test (expected = IllegalArgumentException.class)
public void parseQueryMTypeWGroupByNoSuchFilter() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{host=nosuchfilter(*tsort)}"
+ "{host=dummyfilter(*quirm)}");
parseQuery.invoke(rpc, tsdb, query, expressions);
}
@Test
public void parseQueryMTypeWEmptyFilterBrackets() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0{}{}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
sub.validateAndSetQuery();
assertEquals(0, sub.getFilters().size());
}
@Test
public void parseQueryMTypeWExplicit() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:explicit_tags:sys.cpu.0{host=web01}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub.getTags());
assertEquals("literal_or(web01)", sub.getTags().get("host"));
assertTrue(sub.getExplicitTags());
}
@Test
public void parseQueryMTypeWExplicitAndRate() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:explicit_tags:rate:sys.cpu.0{host=web01}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub.getTags());
assertEquals("literal_or(web01)", sub.getTags().get("host"));
assertTrue(sub.getRate());
assertTrue(sub.getExplicitTags());
}
@Test
public void parseQueryMTypeWExplicitAndRateAndDS() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:explicit_tags:rate:1m-sum:sys.cpu.0{host=web01}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub.getTags());
assertEquals("literal_or(web01)", sub.getTags().get("host"));
assertTrue(sub.getRate());
assertTrue(sub.getExplicitTags());
assertEquals("1m-sum", sub.getDownsample());
}
@Test
public void parseQueryMTypeWExplicitAndDSAndRate() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:explicit_tags:1m-sum:rate:sys.cpu.0{host=web01}");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub.getTags());
assertEquals("literal_or(web01)", sub.getTags().get("host"));
assertTrue(sub.getRate());
assertTrue(sub.getExplicitTags());
assertEquals("1m-sum", sub.getDownsample());
}
@Test
public void parseQueryTSUIDType() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&tsuid=sum:010101");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
assertNotNull(tsq);
assertEquals("1h-ago", tsq.getStart());
assertNotNull(tsq.getQueries());
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub);
assertEquals("sum", sub.getAggregator());
assertEquals(1, sub.getTsuids().size());
assertEquals("010101", sub.getTsuids().get(0));
}
@Test
public void parseQueryTSUIDTypeMulti() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&tsuid=sum:010101,020202");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
assertNotNull(tsq);
assertEquals("1h-ago", tsq.getStart());
assertNotNull(tsq.getQueries());
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub);
assertEquals("sum", sub.getAggregator());
assertEquals(2, sub.getTsuids().size());
assertEquals("010101", sub.getTsuids().get(0));
assertEquals("020202", sub.getTsuids().get(1));
}
@Test
public void parseQuery2TSUIDType() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&tsuid=sum:010101&tsuid=avg:020202");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
assertNotNull(tsq);
assertEquals("1h-ago", tsq.getStart());
assertNotNull(tsq.getQueries());
assertEquals(2, tsq.getQueries().size());
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub);
assertEquals("sum", sub.getAggregator());
assertEquals(1, sub.getTsuids().size());
assertEquals("010101", sub.getTsuids().get(0));
sub = tsq.getQueries().get(1);
assertNotNull(sub);
assertEquals("avg", sub.getAggregator());
assertEquals(1, sub.getTsuids().size());
assertEquals("020202", sub.getTsuids().get(0));
}
@Test
public void parseQueryTSUIDTypeWRate() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&tsuid=sum:rate:010101");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
assertNotNull(tsq);
assertEquals("1h-ago", tsq.getStart());
assertNotNull(tsq.getQueries());
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub);
assertEquals("sum", sub.getAggregator());
assertEquals(1, sub.getTsuids().size());
assertEquals("010101", sub.getTsuids().get(0));
assertTrue(sub.getRate());
}
@Test
public void parseQueryTSUIDTypeWDS() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&tsuid=sum:1m-sum:010101");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
assertNotNull(tsq);
assertEquals("1h-ago", tsq.getStart());
assertNotNull(tsq.getQueries());
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub);
assertEquals("sum", sub.getAggregator());
assertEquals(1, sub.getTsuids().size());
assertEquals("010101", sub.getTsuids().get(0));
assertEquals("1m-sum", sub.getDownsample());
}
@Test
public void parseQueryTSUIDTypeWRateAndDS() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&tsuid=sum:1m-sum:rate:010101");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
assertNotNull(tsq);
assertEquals("1h-ago", tsq.getStart());
assertNotNull(tsq.getQueries());
TSSubQuery sub = tsq.getQueries().get(0);
assertNotNull(sub);
assertEquals("sum", sub.getAggregator());
assertEquals(1, sub.getTsuids().size());
assertEquals("010101", sub.getTsuids().get(0));
assertEquals("1m-sum", sub.getDownsample());
assertTrue(sub.getRate());
}
@Test
public void parseQueryWPadding() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.0&padding");
TSQuery tsq = (TSQuery) parseQuery.invoke(rpc, tsdb, query, expressions);
assertNotNull(tsq);
assertTrue(tsq.getPadding());
}
@Test (expected = BadRequestException.class)
public void parseQueryStartMissing() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?end=1h-ago&m=sum:sys.cpu.0");
parseQuery.invoke(rpc, tsdb, query, expressions);
}
@Test (expected = BadRequestException.class)
public void parseQueryNoSubQuery() throws Exception {
HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago");
parseQuery.invoke(rpc, tsdb, query, expressions);
}
@Test
public void postQuerySimplePass() throws Exception {
final DataPoints[] datapoints = new DataPoints[1];
datapoints[0] = new MockDataPoints().getMock();
when(query_result.runAsync()).thenReturn(
Deferred.fromResult(datapoints));
HttpQuery query = NettyMocks.postQuery(tsdb, "/api/query",
"{\"start\":1425440315306,\"queries\":" +
"[{\"metric\":\"somemetric\",\"aggregator\":\"sum\",\"rate\":true," +
"\"rateOptions\":{\"counter\":false}}]}");
NettyMocks.mockChannelFuture(query);
rpc.execute(tsdb, query);
assertEquals(HttpResponseStatus.OK, query.response().getStatus());
}
@Test
public void postQueryNoMetricBadRequest() throws Exception {
final DeferredGroupException dge = mock(DeferredGroupException.class);
when(dge.getCause()).thenReturn(new NoSuchUniqueName("foo", "metrics"));
when(query_result.configureFromQuery((TSQuery)any(), anyInt()))
.thenReturn(Deferred.fromError(dge));
HttpQuery query = NettyMocks.postQuery(tsdb, "/api/query",
"{\"start\":1425440315306,\"queries\":" +
"[{\"metric\":\"nonexistent\",\"aggregator\":\"sum\",\"rate\":true," +
"\"rateOptions\":{\"counter\":false}}]}");
rpc.execute(tsdb, query);
assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
final String json =
query.response().getContent().toString(Charset.forName("UTF-8"));
assertTrue(json.contains("No such name for 'foo': 'metrics'"));
}
@Test
public void executeEmpty() throws Exception {
final HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.user");
NettyMocks.mockChannelFuture(query);
rpc.execute(tsdb, query);
final String json =
query.response().getContent().toString(Charset.forName("UTF-8"));
assertEquals("[]", json);
}
@Test
public void execute() throws Exception {
final DataPoints[] datapoints = new DataPoints[1];
datapoints[0] = new MockDataPoints().getMock();
when(query_result.runAsync()).thenReturn(
Deferred.fromResult(datapoints));
final HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.user");
NettyMocks.mockChannelFuture(query);
rpc.execute(tsdb, query);
final String json =
query.response().getContent().toString(Charset.forName("UTF-8"));
assertTrue(json.contains("\"metric\":\"system.cpu.user\""));
}
@Test
public void executeNSU() throws Exception {
final DeferredGroupException dge = mock(DeferredGroupException.class);
when(dge.getCause()).thenReturn(new NoSuchUniqueName("foo", "metrics"));
when(query_result.configureFromQuery((TSQuery)any(), anyInt()))
.thenReturn(Deferred.fromError(dge));
final HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:sys.cpu.user");
rpc.execute(tsdb, query);
assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
final String json =
query.response().getContent().toString(Charset.forName("UTF-8"));
assertTrue(json.contains("No such name for 'foo': 'metrics'"));
}
@Test
public void executeWithBadDSFill() throws Exception {
final DataPoints[] datapoints = new DataPoints[1];
datapoints[0] = new MockDataPoints().getMock();
when(query_result.runAsync()).thenReturn(
Deferred.fromResult(datapoints));
try {
final HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query?start=1h-ago&m=sum:10m-avg-badbadbad:sys.cpu.user");
rpc.execute(tsdb, query);
fail("expected BadRequestException");
} catch (final BadRequestException exn) {
System.out.println(exn.getMessage());
assertTrue(exn.getMessage().startsWith(
"Unrecognized fill policy: badbadbad"));
}
}
@Test (expected = BadRequestException.class)
public void deleteDatapointsBadRequest() throws Exception {
HttpQuery query = NettyMocks.deleteQuery(tsdb,
"/api/query?start=1356998400&m=sum:sys.cpu.user", "");
rpc.execute(tsdb, query);
assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
final String json =
query.response().getContent().toString(Charset.forName("UTF-8"));
assertTrue(json.contains("Deleting data is not enabled"));
}
@Test
public void gexp() throws Exception {
final DataPoints[] datapoints = new DataPoints[1];
datapoints[0] = new MockDataPoints().getMock();
when(query_result.runAsync()).thenReturn(
Deferred.fromResult(datapoints));
final HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query/gexp?start=1h-ago&exp=scale(sum:sys.cpu.user,1)");
NettyMocks.mockChannelFuture(query);
rpc.execute(tsdb, query);
assertEquals(query.response().getStatus(), HttpResponseStatus.OK);
final String json =
query.response().getContent().toString(Charset.forName("UTF-8"));
assertTrue(json.contains("\"metric\":\"system.cpu.user\""));
}
@Test
public void gexpBadExpression() throws Exception {
final DataPoints[] datapoints = new DataPoints[1];
datapoints[0] = new MockDataPoints().getMock();
when(query_result.runAsync()).thenReturn(
Deferred.fromResult(datapoints));
final HttpQuery query = NettyMocks.getQuery(tsdb,
"/api/query/gexp?start=1h-ago&exp=scale(sum:sys.cpu.user,notanumber)");
rpc.execute(tsdb, query);
assertEquals(query.response().getStatus(), HttpResponseStatus.BAD_REQUEST);
final String json =
query.response().getContent().toString(Charset.forName("UTF-8"));
assertTrue(json.contains("factor"));
}
//TODO(cl) add unit tests for the rate options parsing
}