// 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.assertNull;
import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.List;
import net.opentsdb.core.DataPoints;
import net.opentsdb.core.TSQuery;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"javax.management.*", "javax.xml.*",
"ch.qos.*", "org.slf4j.*",
"com.sum.*", "org.xml.*"})
@PrepareForTest({ TSQuery.class })
public class TestExpressions {
private TSQuery data_query;
private List<String> metric_queries;
@Before
public void before() throws Exception {
data_query = mock(TSQuery.class);
metric_queries = new ArrayList<String>();
ExpressionFactory.addFunction("foo", new FooExpression());
}
@Test
public void parse() throws Exception {
final ExpressionTree tree = Expressions.parse(
"scale(sys.cpu)", metric_queries, data_query);
assertEquals("scale()", tree.toString());
}
@Test
public void parseWithWhitespace() throws Exception {
final ExpressionTree tree = Expressions.parse(
" scale(sys.cpu)", metric_queries, data_query);
assertEquals("scale()", tree.toString());
}
@Test
public void parseMultiParameter() {
final String expr = "foo(sum:proc.sys.cpu,, sum:proc.meminfo.memfree)";
final ExpressionTree tree = Expressions.parse(expr, metric_queries, null);
assertEquals("foo(proc.sys.cpu,proc.meminfo.memfree)", tree.toString());
assertEquals(2, metric_queries.size());
assertEquals("sum:proc.sys.cpu", metric_queries.get(0));
assertEquals("sum:proc.meminfo.memfree", metric_queries.get(1));
assertNull(tree.funcParams());
}
@Test
public void parseNestedExpr() {
final String expr = "foo(sum:proc.sys.cpu,, foo(sum:proc.a.b))";
final ExpressionTree tree = Expressions.parse(expr, metric_queries, null);
assertEquals("foo(foo(proc.a.b),proc.sys.cpu)", tree.toString());
assertEquals(2, metric_queries.size());
assertEquals("sum:proc.sys.cpu", metric_queries.get(0));
assertEquals("sum:proc.a.b", metric_queries.get(1));
assertNull(tree.funcParams());
}
@Test
public void parseExprWithParam() {
final String expr = "foo(sum:proc.sys.cpu,, 100,, 3.1415)";
final ExpressionTree tree = Expressions.parse(expr, metric_queries, null);
assertEquals("foo(proc.sys.cpu)", tree.toString());
assertEquals(1, metric_queries.size());
assertEquals("sum:proc.sys.cpu", metric_queries.get(0));
assertEquals(2, tree.funcParams().size());
assertEquals("100", tree.funcParams().get(0));
assertEquals("3.1415", tree.funcParams().get(1));
}
@Test (expected = IllegalArgumentException.class)
public void parseNullExpression() throws Exception {
Expressions.parse(null, metric_queries, data_query);
}
@Test (expected = IllegalArgumentException.class)
public void parseEmptyExpression() throws Exception {
Expressions.parse("", metric_queries, data_query);
}
@Test (expected = IllegalArgumentException.class)
public void parseMissingOpenParens() throws Exception {
Expressions.parse("scalesys.cpu)", metric_queries, data_query);
}
@Test (expected = IllegalArgumentException.class)
public void parseMissingClosingParens() throws Exception {
Expressions.parse("scale(sys.cpu", metric_queries, data_query);
}
// TODO - These two may be problematic and need validation/fixing?
@Test
public void parseNullMetricQueries() throws Exception {
final ExpressionTree tree = Expressions.parse(
"scale(sys.cpu)", null, data_query);
assertEquals("scale()", tree.toString());
}
@Test
public void parseNullTSQuery() throws Exception {
final ExpressionTree tree = Expressions.parse(
"scale(sys.cpu)", metric_queries, null);
assertEquals("scale()", tree.toString());
}
//TODO - Need to add more tests around parsing nested functions and params
/** Dummy test expression implementation */
private static class FooExpression implements Expression {
@Override
public DataPoints[] evaluate(final TSQuery data_query,
final List<DataPoints[]> query_results, final List<String> params) {
return new DataPoints[0];
}
@Override
public String writeStringField(final List<String> query_params,
final String inner_expressions) {
return "foo(" + inner_expressions + ")";
}
}
}