/*******************************************************************************
* 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.rrd.jrobin;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jrobin.core.RrdDb;
import org.jrobin.core.RrdDef;
import org.jrobin.core.Sample;
import org.jrobin.graph.RrdGraph;
import org.jrobin.graph.RrdGraphDef;
import org.jrobin.graph.RrdGraphInfo;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.opennms.core.test.MockLogAppender;
import org.opennms.netmgt.rrd.RrdDataSource;
import org.opennms.netmgt.rrd.RrdException;
import org.opennms.netmgt.rrd.RrdGraphDetails;
import org.opennms.netmgt.rrd.RrdStrategy;
import org.opennms.netmgt.rrd.RrdUtils;
import org.opennms.test.FileAnticipator;
import org.opennms.test.ThrowableAnticipator;
import org.opennms.test.mock.MockUtil;
import org.springframework.util.StringUtils;
/**
* Unit tests for the JrobinRrdStrategy.
*
* @author <a href="mailto:dj@opennms.org">DJ Gregor</a>
*/
public class JRobinRrdStrategyTest {
private RrdStrategy<RrdDef,RrdDb> m_strategy;
private FileAnticipator m_fileAnticipator;
@Before
public void setUp() throws Exception {
// Make sure that AWT headless mode is enabled
System.setProperty("java.awt.headless", "true");
MockLogAppender.setupLogging(true, "DEBUG");
m_strategy = new JRobinRrdStrategy();
// Don't initialize by default since not all tests need it.
m_fileAnticipator = new FileAnticipator(false);
}
@After
public void tearDown() throws Exception {
if (m_fileAnticipator.isInitialized()) {
m_fileAnticipator.deleteExpected();
}
m_fileAnticipator.tearDown();
}
@Test
public void testInitialize() {
// Don't do anything... just check that setUp works
}
@Test
public void testCommandWithoutDrawing() throws Exception {
long end = System.currentTimeMillis();
long start = end - (24 * 60 * 60 * 1000);
String command = "--start=" + start + " --end=" + end;
ThrowableAnticipator ta = new ThrowableAnticipator();
ta.anticipate(new RrdException(ThrowableAnticipator.IGNORE_MESSAGE));
try {
m_strategy.createGraph(command, new File(""));
} catch (Throwable t) {
ta.throwableReceived(t);
// We don't care about the exact message, just a few details
String problemText = "no graph was produced";
assertTrue("cause message should contain '" + problemText + "'", t.getMessage().contains(problemText));
String suggestionText = "Does the command have any drawing commands";
assertTrue("cause message should contain '" + suggestionText + "'", t.getMessage().contains(suggestionText));
}
ta.verifyAnticipated();
}
@Test
public void testDefWithEscapedCharacters() throws Exception {
long end = System.currentTimeMillis() / 1000;
long start = end - (24 * 60 * 60);
final String[] command = new String[] {
"--start=" + (start - 300),
"--end=" + (end + 300),
"DEF:baz=response/fe80\\:0000\\:0000\\:0000\\:0000\\:0000\\:0000\\:0000\\%5/dns.jrb:bar:AVERAGE",
"VDEF:avg=baz,AVERAGE",
"VDEF:min=baz,MIN",
"VDEF:max=baz,MAX",
"VDEF:tot=baz,TOTAL",
"VDEF:nfp=baz,95,PERCENT",
"PRINT:avg:AVERAGE:\"%le\"",
"PRINT:min:AVERAGE:\"%le\"",
"PRINT:max:AVERAGE:\"%le\"",
"PRINT:tot:AVERAGE:\"%le\"",
"PRINT:nfp:AVERAGE:\"%le\""
};
Throwable t = null;
try {
((JRobinRrdStrategy)m_strategy).createGraphDef(new File(""), command);
} catch (final org.jrobin.core.RrdException e) {
t = e;
}
assertNotNull(t);
assertTrue("message was " + t.getMessage(), t.getMessage().contains("Could not open "));
assertTrue("message was " + t.getMessage(), t.getMessage().contains("fe80:0000:0000:0000:0000:0000:0000:0000%5"));
}
@Test
public void testCreate() throws Exception {
File rrdFile = createRrdFile();
RrdDb openedFile = m_strategy.openFile(rrdFile.getAbsolutePath());
//m_strategy.updateFile(openedFile, "huh?", "N:1,234234");
Sample sample = ((RrdDb) openedFile).createSample();
sample.set("N:1.234 something not that politically incorrect");
System.err.println(sample.dump());
m_strategy.closeFile(openedFile);
}
@Test
public void testUpdate() throws Exception {
File rrdFile = createRrdFile();
RrdDb openedFile = m_strategy.openFile(rrdFile.getAbsolutePath());
m_strategy.updateFile(openedFile, "huh?", "N:1.234234");
m_strategy.closeFile(openedFile);
}
@Test
public void testSampleSetFloatingPointValueGood() throws Exception {
File rrdFile = createRrdFile();
RrdDb openedFile = m_strategy.openFile(rrdFile.getAbsolutePath());
Sample sample = openedFile.createSample();
sample.set("N:1.234");
m_strategy.closeFile(openedFile);
double[] values = sample.getValues();
assertEquals("values list size", 1, values.length);
assertEquals("values item 0", 1.234, values[0], 0.0);
}
@Test
public void testSampleVDEFPercentile() throws Exception {
Double[] vals = {
39.0, 94.0, 95.0, 101.0, 155.0, 262.0, 274.0, 302.0, 319.0, 402.0, 466.0, 468.0, 494.0, 549.0, 550.0, 575.0, 600.0, 615.0, 625.0, 703.0, 729.0, 824.0, 976.0, 1018.0, 1036.0, 1138.0, 1195.0, 1265.0, 1287.0, 1323.0, 1410.0, 1443.0, 1516.0, 1538.0, 1664.0, 1686.0, 1801.0, 1912.0, 1921.0, 1929.0, 1936.0, 1941.0, 1985.0, 2003.0, 2010.0, 2013.0, 2082.0, 2106.0, 2213.0, 2358.0, 2394.0, 2572.0, 2616.0, 2627.0, 2676.0, 2694.0, 2736.0, 2740.0, 2966.0, 3005.0, 3037.0, 3041.0, 3146.0, 3194.0, 3228.0, 3235.0, 3243.0, 3339.0, 3365.0, 3414.0, 3440.0, 3454.0, 3567.0, 3570.0, 3615.0, 3619.0, 3802.0, 3831.0, 3864.0, 4061.0, 4084.0, 4106.0, 4233.0, 4328.0, 4362.0, 4372.0, 4376.0, 4388.0, 4413.0, 4527.0, 4612.0, 4643.0, 4684.0, 4750.0, 4799.0, 4810.0, 4824.0, 4825.0, 4871.0, 4932.0, 5028.0, 5112.0, 5118.0, 5163.0, 5198.0, 5256.0, 5296.0, 5413.0, 5471.0, 5568.0, 5628.0, 5645.0, 5733.0, 5790.0, 5851.0, 5886.0, 5927.0, 5937.0, 6018.0, 6027.0, 6046.0, 6145.0, 6147.0, 6289.0, 6371.0, 6384.0, 6393.0, 6431.0, 6469.0, 6543.0, 6649.0, 6772.0, 6864.0, 6943.0, 7009.0, 7014.0, 7037.0, 7258.0, 7356.0, 7364.0, 7386.0, 7387.0, 7399.0, 7450.0, 7519.0, 7527.0, 7578.0, 7632.0, 7709.0, 7849.0, 7896.0, 7952.0, 7980.0, 8050.0, 8126.0, 8152.0, 8165.0, 8332.0, 8347.0, 8520.0, 8522.0, 8542.0, 8587.0, 8621.0, 8678.0, 8721.0, 8739.0, 8765.0, 8889.0, 8951.0, 8962.0, 9082.0, 9149.0, 9199.0, 9278.0, 9334.0, 9339.0, 9345.0, 9365.0, 9383.0, 9402.0, 9471.0, 9483.0, 9492.0, 9496.0, 9532.0, 9553.0, 9563.0, 9571.0, 9574.0, 100000.0, 120000.0, 150000.0, 200000.0, 500000.0, 1000000.0, 2000000.0, 4000000.0, 8000000.0, 16000000.0
};
File rrdFile = createRrdFile();
RrdDb openedFile = m_strategy.openFile(rrdFile.getAbsolutePath());
// This file's step size is 300
int endTime = (int)(System.currentTimeMillis() / 1000);
endTime -= (endTime % 300);
int startTime = endTime - (200 * 300);
// Got to throw away the first sample
m_strategy.updateFile(openedFile, "huh?", (startTime - 300) + ":" + "0.0");
int sampleTime = startTime;
for (double val : vals) {
m_strategy.updateFile(openedFile, "huh?", sampleTime + ":" + val);
sampleTime += 300;
}
m_strategy.closeFile(openedFile);
String[] command;
RrdGraphDef graphDef;
RrdGraph graph;
RrdGraphInfo info;
String[] printLines;
command = new String[] {
"--start=" + (startTime - 300),
"--end=" + (endTime + 300),
"DEF:baz=" + rrdFile.getAbsolutePath().replace("\\", "\\\\") + ":bar:AVERAGE",
"VDEF:avg=baz,AVERAGE",
"VDEF:min=baz,MIN",
"VDEF:max=baz,MAX",
"VDEF:tot=baz,TOTAL",
"VDEF:nfp=baz,95,PERCENT",
"PRINT:avg:AVERAGE:\"%le\"",
"PRINT:min:AVERAGE:\"%le\"",
"PRINT:max:AVERAGE:\"%le\"",
"PRINT:tot:AVERAGE:\"%le\"",
"PRINT:nfp:AVERAGE:\"%le\""
};
graphDef = ((JRobinRrdStrategy)m_strategy).createGraphDef(new File(""), command);
graph = new RrdGraph(graphDef);
assertNotNull("graph object", graph);
info = graph.getRrdGraphInfo();
assertNotNull("graph info object", info);
printLines = info.getPrintLines();
assertNotNull("graph printLines - DEF", printLines);
assertEquals("graph printLines - DEF size", 5, printLines.length);
assertEquals("graph printLines - DEF item 0", "1.649453e+05", printLines[0]);
assertEquals("graph printLines - DEF item 1", "3.900000e+01", printLines[1]);
assertEquals("graph printLines - DEF item 2", "1.600000e+07", printLines[2]);
assertEquals("graph printLines - DEF item 3", "9.896721e+09", printLines[3]);
assertEquals("graph printLines - DEF item 4", "9.574000e+03", printLines[4]);
// Now do it with a CDEF
command = new String[] {
"--start=" + (startTime - 300),
"--end=" + (endTime + 300),
"DEF:baz=" + rrdFile.getAbsolutePath().replace("\\", "\\\\") + ":bar:AVERAGE",
"CDEF:bazX1=baz,1,*",
"CDEF:bazX1P0=bazX1,0,+",
"VDEF:avg=bazX1,AVERAGE",
"VDEF:min=bazX1,MIN",
"VDEF:max=bazX1,MAX",
"VDEF:tot=bazX1,TOTAL",
"VDEF:nfp=bazX1,95,PERCENT",
"VDEF:nfp2=bazX1P0,95,PERCENT",
"PRINT:avg:AVERAGE:\"%le\"",
"PRINT:min:AVERAGE:\"%le\"",
"PRINT:max:AVERAGE:\"%le\"",
"PRINT:tot:AVERAGE:\"%le\"",
"PRINT:nfp:AVERAGE:\"%le\"",
"PRINT:nfp2:AVERAGE:\"%le\""
};
graphDef = ((JRobinRrdStrategy)m_strategy).createGraphDef(new File(""), command);
graph = new RrdGraph(graphDef);
assertNotNull("graph object", graph);
info = graph.getRrdGraphInfo();
assertNotNull("graph info object", info);
printLines = info.getPrintLines();
assertNotNull("graph printLines - CDEF", printLines);
assertEquals("graph printLines - CDEF size", 6, printLines.length);
assertEquals("graph printLines - CDEF item 0", "1.649453e+05", printLines[0]);
assertEquals("graph printLines - CDEF item 1", "3.900000e+01", printLines[1]);
assertEquals("graph printLines - CDEF item 2", "1.600000e+07", printLines[2]);
assertEquals("graph printLines - CDEF item 3", "9.896721e+09", printLines[3]);
assertEquals("graph printLines - CDEF item 4", "9.574000e+03", printLines[4]);
assertEquals("graph printLines - CDEF item 5", "9.574000e+03", printLines[5]);
}
/**
* This test fails because of
* <a href="http://bugzilla.opennms.org/show_bug.cgi?id=2272">bug #2272</a>
* in org.jrobin.core.Sample.
*/
@Test
@Ignore("fails due to bug 2272")
public void testSampleSetFloatingPointValueWithComma() throws Exception {
File rrdFile = createRrdFile();
RrdDb openedFile = m_strategy.openFile(rrdFile.getAbsolutePath());
Sample sample = openedFile.createSample();
sample.set("N:1,234");
m_strategy.closeFile(openedFile);
double[] values = sample.getValues();
assertEquals("values list size", 1, values.length);
assertEquals("values item 0", 1.234, values[0], 0.0);
}
/**
* This test fails because of
* <a href="http://bugzilla.opennms.org/show_bug.cgi?id=2272">bug #2272</a>
* in org.jrobin.core.Sample.
*/
@Test
@Ignore("fails due to bug 2272")
public void testSampleSetFloatingPointValueWithExtraJunk() throws Exception {
File rrdFile = createRrdFile();
RrdDb openedFile = m_strategy.openFile(rrdFile.getAbsolutePath());
Sample sample = openedFile.createSample();
ThrowableAnticipator ta = new ThrowableAnticipator();
ta.anticipate(new Exception("Some exception that complains about bogus data"));
try {
sample.set("N:1.234 extra junk");
} catch (Throwable t) {
ta.throwableReceived(t);
} finally {
m_strategy.closeFile(openedFile);
}
ta.verifyAnticipated();
}
@Test
public void testCommentWithNewlines() throws Exception {
long end = System.currentTimeMillis();
long start = end - (24 * 60 * 60 * 1000);
String[] command = new String[] {
"--start=" + start,
"--end=" + end,
"COMMENT:foo\\n"
};
String[] command2 = new String[] {
"--start=" + start,
"--end=" + end,
"COMMENT:foo\\n",
"COMMENT:foo2\\n"
};
RrdGraphDef graphDef = ((JRobinRrdStrategy)m_strategy).createGraphDef(new File(""), command);
RrdGraph graph = new RrdGraph(graphDef);
assertNotNull("graph object", graph);
int firstHeight = graph.getRrdGraphInfo().getHeight();
RrdGraphDef graphDef2 = ((JRobinRrdStrategy)m_strategy).createGraphDef(new File(""), command2);
RrdGraph graph2 = new RrdGraph(graphDef2);
assertNotNull("second graph object", graph2);
int secondHeight = graph2.getRrdGraphInfo().getHeight();
assertFalse("first graph height " + firstHeight + " and second graph height " + secondHeight + " should not be equal... there should be another newline in the second one making it taller", firstHeight == secondHeight);
}
@Test
public void testGprintWithNewlines() throws Exception {
long end = System.currentTimeMillis();
long start = end - (24 * 60 * 60 * 1000);
String[] command = new String[] {
"--start=" + start,
"--end=" + end,
"CDEF:a=1",
"GPRINT:a:AVERAGE:\"%8.2lf\\n\""
};
String[] command2 = new String[] {
"--start=" + start,
"--end=" + end,
"CDEF:a=1",
"CDEF:b=1",
"GPRINT:a:AVERAGE:\"%8.2lf\\n\"",
"GPRINT:b:AVERAGE:\"%8.2lf\\n\""
};
RrdGraphDef graphDef = ((JRobinRrdStrategy)m_strategy).createGraphDef(new File(""), command);
RrdGraph graph = new RrdGraph(graphDef);
assertNotNull("graph object", graph);
int firstHeight = graph.getRrdGraphInfo().getHeight();
RrdGraphDef graphDef2 = ((JRobinRrdStrategy)m_strategy).createGraphDef(new File(""), command2);
RrdGraph graph2 = new RrdGraph(graphDef2);
assertNotNull("second graph object", graph2);
int secondHeight = graph2.getRrdGraphInfo().getHeight();
assertFalse("first graph height " + firstHeight + " and second graph height " + secondHeight + " should not be equal... there should be another line with a newline in the second one making it taller", firstHeight == secondHeight);
}
@Test
public void testPrint() throws Exception {
long end = System.currentTimeMillis();
long start = end - (24 * 60 * 60 * 1000);
String[] command = new String[] {
"--start=" + start,
"--end=" + end,
"CDEF:something=1",
"PRINT:something:AVERAGE:\"%le\""
};
RrdGraphDef graphDef = ((JRobinRrdStrategy)m_strategy).createGraphDef(new File(""), command);
RrdGraph graph = new RrdGraph(graphDef);
assertNotNull("graph object", graph);
RrdGraphInfo info = graph.getRrdGraphInfo();
assertNotNull("graph info object", info);
String[] printLines = info.getPrintLines();
assertNotNull("graph printLines", printLines);
assertEquals("graph printLines size", 1, printLines.length);
assertEquals("graph printLines item 0", "1.000000e+00", printLines[0]);
double d = Double.parseDouble(printLines[0]);
assertEquals("graph printLines item 0 as a double", 1.0, d, 0.0);
}
@Test
public void testPrintThroughInterface() throws Exception {
long end = System.currentTimeMillis();
long start = end - (24 * 60 * 60 * 1000);
String[] command = new String[] {
"--start=" + start,
"--end=" + end,
"CDEF:something=1",
"PRINT:something:AVERAGE:\"%le\""
};
RrdGraphDetails graphDetails = m_strategy.createGraphReturnDetails(StringUtils.arrayToDelimitedString(command, " "), new File(""));
assertNotNull("graph details object", graphDetails);
String[] printLines = graphDetails.getPrintLines();
assertNotNull("graph printLines", printLines);
assertEquals("graph printLines size", 1, printLines.length);
assertEquals("graph printLines item 0", "1.000000e+00", printLines[0]);
double d = Double.parseDouble(printLines[0]);
assertEquals("graph printLines item 0 as a double", 1.0, d, 0.0);
}
@Test
public void testTWQnENoQNoE() throws Exception {
String input = "This string has no quoting and no escapes";
String[] expected = new String[] { "This", "string", "has", "no", "quoting", "and", "no", "escapes" };
String[] actual = JRobinRrdStrategy.tokenizeWithQuotingAndEscapes(input, " ", false, "");
assertEquals(Arrays.asList(expected), Arrays.asList(actual));
}
@Test
public void testTWQnENoQNoEWithDEFUnix() throws Exception {
if (File.separatorChar != '/') {
MockUtil.println("-------- Skipping testTWQnENoQNoEWithDEFUnix since File.separator is not / ------------");
MockUtil.println("-------- Be sure to run the tests on Unix too! ---------");
return;
}
String input = "No quote, no escapes, but DEF:test=snmp/42/test.jrb:test:AVERAGE";
String[] expected = new String[] { "No", "quote,", "no", "escapes,", "but", "DEF:test=snmp/42/test.jrb:test:AVERAGE" };
String[] actual = JRobinRrdStrategy.tokenizeWithQuotingAndEscapes(input, " ", false, "");
assertEquals(Arrays.asList(expected), Arrays.asList(actual));
}
@Test
public void testTWQnENoQNoEWithDEFWindows() throws Exception {
// This test case inspired by bug #2223
if (File.separatorChar != '\\') {
MockUtil.println("-------- Skipping testTWQnENoQNoEWithDEFWindows since File.separator is not \\ ------------");
MockUtil.println("-------- Be sure to run the tests on Windows too! ---------");
return;
}
String input = "No quote, no escapes, but DEF:test=snmp\\42\\test.jrb:test:AVERAGE";
String[] expected = new String[] { "No", "quote,", "no", "escapes,", "but", "DEF:test=snmp\\42\\test.jrb:test:AVERAGE" };
String[] actual = JRobinRrdStrategy.tokenizeWithQuotingAndEscapes(input, " ", false, "");
assertEquals(Arrays.asList(expected), Arrays.asList(actual));
}
public File createRrdFile() throws Exception {
String rrdFileBase = "foo";
m_fileAnticipator.initialize();
String rrdExtension = RrdUtils.getExtension();
List<RrdDataSource> dataSources = new ArrayList<RrdDataSource>();
dataSources.add(new RrdDataSource("bar", "GAUGE", 3000, "U", "U"));
List<String> rraList = new ArrayList<String>();
rraList.add("RRA:AVERAGE:0.5:1:2016");
RrdDef def = m_strategy.createDefinition("hello!", m_fileAnticipator.getTempDir().getAbsolutePath(), rrdFileBase, 300, dataSources, rraList);
m_strategy.createFile(def);
return m_fileAnticipator.expecting(rrdFileBase + rrdExtension);
}
}