/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2007-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.netmgt.threshd;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.opennms.netmgt.config.threshd.Expression;
import junit.framework.TestCase;
/**
* A lot of these tests could be construed as checking that JEP is working properly (which we kind of assume
* to be the case anyway).
* Therefore on one hand, they are "belt-and-britches" security (affirming that JEP works). On the other
* we also still need to test that our integration with JEP works as expected (e.g., that there are no oddities
* with the intepretation of operators or the like)
*
* @author <a href="mailto:cmiskell@opennms.org">Craig Miskell</a>
*
*/
public class ThresholdExpressionTestCase extends TestCase {
Expression expression;
public void setUp() {
expression=new Expression();
expression.setType("high");
expression.setDsType("ds-type");
expression.setValue(99.0);
expression.setRearm(0.5);
expression.setTrigger(1);
}
public void testEvaluateEvaluateSingleItemWithDivision() throws Exception {
expression.setExpression("dsname/10");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(1, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "dsname" }) {
assertTrue(wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("dsname",1000.0);
double result=wrapper.evaluate(values);
assertEquals("Threshold Expression result", new Double(result), new Double(100.0));
}
public void testEvaluateEvaluateSingleItemWithMultiply() throws Exception {
expression.setExpression("dsname*10");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(1, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "dsname" }) {
assertTrue(wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("dsname",100.0);
double result=wrapper.evaluate(values);
assertEquals("Threshold Expression result", new Double(result), new Double(1000.0));
}
public void testEvaluateEvaluateSingleItemWithSubtraction() throws Exception {
expression.setExpression("dsname-10");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(1, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "dsname" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("dsname",100.0);
double result=wrapper.evaluate(values);
assertEquals("Threshold Expression result", new Double(result), new Double(90.0));
}
public void testEvaluateEvaluateSingleItemWithAddition() throws Exception {
expression.setExpression("dsname+10");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(1, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "dsname" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("dsname",100.0);
double result=wrapper.evaluate(values);
assertEquals("Threshold Expression result", new Double(result), new Double(110.0));
}
public void testEvaluateEvaluateMultipleItemsDivided() throws Exception {
expression.setExpression("dsname1/dsname2");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(2, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "dsname1", "dsname2" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("dsname1",100.0);
values.put("dsname2",5.0);
double result=wrapper.evaluate(values);
assertEquals("Threshold Expression result", new Double(result), new Double(20.0));
}
public void testEvaluateEvaluateMultipleItemsMultiplied() throws Exception {
expression.setExpression("dsname1*dsname2");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(2, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "dsname1", "dsname2" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("dsname1",20.0);
values.put("dsname2",5.0);
double result=wrapper.evaluate(values);
assertEquals("Threshold Expression result", new Double(result), new Double(100.0));
}
public void testEvaluateEvaluateMultipleItemsAdded() throws Exception {
expression.setExpression("dsname1+dsname2");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(2, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "dsname1", "dsname2" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("dsname1",20.0);
values.put("dsname2",5.0);
double result=wrapper.evaluate(values);
assertEquals("Threshold Expression result", new Double(result), new Double(25.0));
}
public void testEvaluateEvaluateMultipleItemsSubtracted() throws Exception {
expression.setExpression("dsname1-dsname2");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(2, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "dsname1", "dsname2" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("dsname1",20.0);
values.put("dsname2",5.0);
double result=wrapper.evaluate(values);
assertEquals("Threshold Expression result", new Double(result), new Double(15.0));
}
/*
* Modelled on an expression that could be required for hrStorageIndex, where
* we want to threshold not on percentage full (which we get from "Used/Size"), but rather
* when free space is lower than some number of bytes (KB, MB, GB, TB, whatever)
*/
public void testSemiComplexExpression() throws Exception {
expression.setExpression("(hrStorageSize-hrStorageUsed)*hrStorageAllocationUnits");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(3, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "hrStorageSize", "hrStorageUsed", "hrStorageAllocationUnits" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("hrStorageAllocationUnits",1024.0); //1K units
values.put("hrStorageSize",2048.0); //2MB total size
values.put("hrStorageUsed",1024.0); //1MB used
double result=wrapper.evaluate(values);
//1MB free, hopefully
assertEquals("Threshold Expression result", new Double(result), new Double(1024.0*1024.0));
}
public void testThresholdEntityRequiredDataSources() throws Exception {
ThresholdEntity entity=new ThresholdEntity();
expression.setExpression("(hrStorageSize-hrStorageUsed)*hrStorageAllocationUnits");
BaseThresholdDefConfigWrapper wrapper=BaseThresholdDefConfigWrapper.getConfigWrapper(expression);
assertEquals(3, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "hrStorageSize", "hrStorageUsed", "hrStorageAllocationUnits" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
entity.addThreshold(wrapper);
Collection<String> dataSources=entity.getRequiredDatasources();
StringBuffer dsStringBuffer = new StringBuffer();
for (String dataSource : dataSources) {
dsStringBuffer.append(dataSource).append(" ");
}
String dsString = dsStringBuffer.toString().trim();
assertTrue("Required data sources should contain hrStorageSize: " + dsString, dataSources.contains("hrStorageSize"));
assertTrue("Required data sources should contain hrStorageUsed: " + dsString, dataSources.contains("hrStorageUsed"));
assertTrue("Required data sources should contain hrStorageAllocationUnits: " + dsString, dataSources.contains("hrStorageAllocationUnits"));
}
public void testEvaluateConditionalFalse() throws Exception {
// Doesn't work because the expression is actually being evaluated to sniff
// the variable names and trueval is never visited by the parser
// expression.setExpression("a < b ? trueval : falseval");
// Force trueval to be visited by the parser
expression.setExpression("(trueval == trueval && a < b) ? trueval : falseval");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(4, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "a", "b", "trueval", "falseval" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("a",20.0);
values.put("b",5.0);
values.put("trueval",3.0);
values.put("falseval",7.0);
double result=wrapper.evaluate(values);
assertEquals("Conditional Expression result", new Double(result), new Double(7.0));
}
public void testEvaluateConditionalTrue() throws Exception {
// Doesn't work because the expression is actually being evaluated to sniff
// the variable names and trueval is never visited by the parser
// expression.setExpression("a < b ? trueval : falseval");
// Force trueval to be visited by the parser
expression.setExpression("(trueval == trueval && a < b) ? trueval : falseval");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(4, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "a", "b", "trueval", "falseval" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
Map<String, Double> values=new HashMap<String,Double>();
values.put("a",2.0);
values.put("b",5.0);
values.put("trueval",3.0);
values.put("falseval",7.0);
double result=wrapper.evaluate(values);
assertEquals("Conditional Expression result", new Double(result), new Double(3.0));
}
public void testAbsoluteValues() throws Exception {
expression.setExpression("math.abs(variable + 5)");
ExpressionConfigWrapper wrapper=new ExpressionConfigWrapper(expression);
assertEquals(1, wrapper.getRequiredDatasources().size());
for (String ds : new String[] { "variable" }) {
assertTrue("Could not find expected variable: " + ds, wrapper.getRequiredDatasources().contains(ds));
}
Map<String,Double> values=new HashMap<String,Double>();
values.put("variable", -25.0);
double result = wrapper.evaluate(values);
assertEquals("Conditional Expression result", new Double(20.0), result);
values.clear();
values.put("variable", 25.0);
result = wrapper.evaluate(values);
assertEquals("Conditional Expression result", new Double(30.0), result);
}
}