package org.rrd4j.core; import static org.rrd4j.ConsolFun.AVERAGE; import static org.rrd4j.ConsolFun.MAX; import static org.rrd4j.ConsolFun.TOTAL; import static org.rrd4j.DsType.GAUGE; import java.io.IOException; import java.net.URL; import java.util.Calendar; import java.util.Random; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.rrd4j.ConsolFun; import org.rrd4j.DsType; import org.rrd4j.data.Aggregates; public class RrdDbTest { static final long SEED = 1909752002L; static final Random RANDOM = new Random(SEED); static final long START = Util.getTimestamp(2010, 4, 1); static final long END = Util.getTimestamp(2010, 6, 1); static final int MAX_STEP = 300; @Rule public TemporaryFolder testFolder = new TemporaryFolder(); public void testRrdDb(RrdDb db) throws IOException { Assert.assertEquals("Invalid step", 300L, db.getHeader().getStep()); Assert.assertEquals("Invalid number of datasources", 2, db.getDsCount()); Assert.assertEquals("Invalid name for first data source", "sun", db.getDatasource(0).getName()); Assert.assertEquals("Invalid dsType for first data source", DsType.GAUGE, db.getDatasource(0).getType()); Assert.assertEquals("Invalid hearthbeat for first data source", 600, db.getDatasource(0).getHeartbeat()); Assert.assertTrue("Invalid max value for first data source", Double.isNaN(db.getDatasource(0).getMaxValue())); Assert.assertEquals("Invalid min value for first data source", 0, db.getDatasource(0).getMinValue(), 1e-7); Assert.assertEquals("Invalid name for second data source", "shade", db.getDatasource(1).getName()); Assert.assertEquals("Invalid dsType for second data source", DsType.GAUGE, db.getDatasource(1).getType()); Assert.assertEquals("Invalid hearthbeat for second data source", 600, db.getDatasource(1).getHeartbeat()); Assert.assertTrue("Invalid max value for second data source", Double.isNaN(db.getDatasource(1).getMaxValue())); Assert.assertEquals("Invalid min value for second data source", 0, db.getDatasource(0).getMinValue(), 1e-7); Assert.assertEquals("Invalid number of archives", 12, db.getArcCount()); Assert.assertEquals("Invalid consolidation function for first archive", ConsolFun.AVERAGE, db.getArchive(0).getConsolFun()); Assert.assertEquals("Invalid number of steps for first archive", 1, db.getArchive(0).getSteps()); Assert.assertEquals("Invalid number of row for first archive", 600, db.getArchive(0).getRows()); Assert.assertEquals("Invalid XFF for first archive", 0.5, db.getArchive(0).getXff(), 1e-7); Assert.assertEquals("Invalid consolidation function for second archive", ConsolFun.AVERAGE, db.getArchive(1).getConsolFun()); Assert.assertEquals("Invalid number of steps for second archive", 6, db.getArchive(1).getSteps()); Assert.assertEquals("Invalid number of row for seconde archive", 700, db.getArchive(1).getRows()); Assert.assertEquals("Invalid XFF for second archive", 0.5, db.getArchive(1).getXff(), 1e-7); } public void testRrdDbXml(RrdDb db) throws IOException { double value; Assert.assertEquals("Invalid date", 920808900L, db.getLastUpdateTime()); Assert.assertEquals("Invalid step", 300L, db.getHeader().getStep()); Assert.assertEquals("Invalid number of datasources", 2, db.getDsCount()); Assert.assertEquals("Invalid name for first data source", "speed", db.getDatasource(0).getName()); Assert.assertEquals("Invalid dsType for first data source", DsType.COUNTER, db.getDatasource(0).getType()); Assert.assertEquals("Invalid hearthbeat for first data source", 600, db.getDatasource(0).getHeartbeat()); Assert.assertTrue("Invalid max value for first data source", Double.isNaN(db.getDatasource(0).getMaxValue())); Assert.assertTrue("Invalid min value for first data source", Double.isNaN(db.getDatasource(0).getMinValue())); Assert.assertEquals("Invalid last value for first data source", 12405, db.getDatasource(0).getLastValue(), 1e-7); Assert.assertEquals("Invalid nan secondes for first data source", 0, db.getDatasource(0).getNanSeconds(), 1e-7); Assert.assertEquals("Invalid name for second data source", "weight", db.getDatasource(1).getName()); Assert.assertEquals("Invalid dsType for second data source", DsType.GAUGE, db.getDatasource(1).getType()); Assert.assertEquals("Invalid hearthbeat for second data source", 600, db.getDatasource(1).getHeartbeat()); Assert.assertTrue("Invalid max value for second data source", Double.isNaN(db.getDatasource(1).getMaxValue())); Assert.assertTrue("Invalid min value for second data source", Double.isNaN(db.getDatasource(1).getMinValue())); value = db.getDatasource(1).getLastValue(); Assert.assertTrue("Invalid last value for second data source", value == 3.0 || Double.isNaN(value)); Assert.assertEquals("Invalid nan secondes for second data source", 0, db.getDatasource(1).getNanSeconds(), 1e-7); Assert.assertEquals("Invalid number of archives", 2, db.getArcCount()); Assert.assertEquals("Invalid consolidation function for first archive", ConsolFun.AVERAGE, db.getArchive(0).getConsolFun()); Assert.assertEquals("Invalid number of steps for first archive", 1, db.getArchive(0).getSteps()); Assert.assertEquals("Invalid number of row for first archive", 24, db.getArchive(0).getRows()); Assert.assertEquals("Invalid XFF for first archive", 0.5, db.getArchive(0).getXff(), 1e-7); Assert.assertEquals("Invalid start time for first archive", 920802000, db.getArchive(0).getStartTime()); Assert.assertEquals("Invalid end time for first archive", 920808900, db.getArchive(0).getEndTime()); value = db.getArchive(0).getArcState(0).getAccumValue(); Assert.assertTrue("Invalid value for first ds in first archive: " + value, Double.isNaN(value)); value = db.getArchive(0).getArcState(1).getAccumValue(); Assert.assertTrue("Invalid value for second ds in first archive: " + value, Double.isNaN(value)); Assert.assertEquals("Invalid consolidation function for second archive", ConsolFun.AVERAGE, db.getArchive(1).getConsolFun()); Assert.assertEquals("Invalid number of steps for second archive", 6, db.getArchive(1).getSteps()); Assert.assertEquals("Invalid number of row for seconde archive", 10, db.getArchive(1).getRows()); Assert.assertEquals("Invalid XFF for second archive", 0.5, db.getArchive(1).getXff(), 1e-7); Assert.assertEquals("Invalid start time for second archive", 920791800, db.getArchive(1).getStartTime()); Assert.assertEquals("Invalid end time for second archive", 920808000, db.getArchive(1).getEndTime()); value = db.getArchive(1).getArcState(0).getAccumValue(); Assert.assertEquals("Invalid value for first ds in second archive: " + value, 1.4316557620e+07, value, 1e-5); value = db.getArchive(1).getArcState(1).getAccumValue(); Assert.assertEquals("Invalid value for second ds in second archive: " + value, 6.0, value, 1e-5); } public void checkValues(RrdDb db) throws IOException { double value; Assert.assertEquals("Invalid date", 1278107831, db.getLastUpdateTime()); Assert.assertEquals("Invalid last value for first data source", 3947, db.getDatasource(0).getLastValue(), 1e-7); Assert.assertEquals("Invalid nan secondes for first data source", 0, db.getDatasource(0).getNanSeconds(), 1e-7); Assert.assertEquals("Invalid nan secondes for second data source", 0, db.getDatasource(1).getNanSeconds(), 1e-7); Assert.assertEquals("Invalid start time for first archive", 1277928000, db.getArchive(0).getStartTime()); Assert.assertEquals("Invalid end time for first archive", 1278107700, db.getArchive(0).getEndTime()); Assert.assertEquals("Invalid start time for second archive", 1276848000, db.getArchive(1).getStartTime()); Assert.assertEquals("Invalid end time for second archive", 1278106200, db.getArchive(1).getEndTime()); value = db.getDatasource(1).getLastValue(); Assert.assertEquals("Invalid last value for second data source", 497, value, 1e-7); value = db.getArchive(0).getArcState(0).getAccumValue(); Assert.assertTrue("Invalid value for first ds in first archive: " + value, Double.isNaN(value)); value = db.getArchive(0).getArcState(1).getAccumValue(); Assert.assertTrue("Invalid value for second ds in first archive: " + value, Double.isNaN(value)); value = db.getArchive(1).getArcState(0).getAccumValue(); Assert.assertEquals("Invalid value for first ds in second archive: " + value, 19757.199999999997, value, 1e-5); value = db.getArchive(1).getArcState(1).getAccumValue(); Assert.assertEquals("Invalid value for second ds in second archive: " + value, 2591.2066666666665, value, 1e-5); FetchData fd = db.createFetchRequest(ConsolFun.AVERAGE, 1277928000, 1278107700).fetchData(); @SuppressWarnings("deprecation") Aggregates speedAggr = fd.getAggregates("sun"); Assert.assertEquals("Invalid average for sun", 1.1985168039e1, speedAggr.getAverage(), 1e-7); Assert.assertEquals("Invalid first for sun", 3.5834466667e3, speedAggr.getFirst(), 1e-7); Assert.assertEquals("Invalid last for sun", 3.9572500000e3, speedAggr.getLast(), 1e-7); Assert.assertEquals("Invalid min for sun", 3.3940000000e3, speedAggr.getMin(), 1e-7); Assert.assertEquals("Invalid max for sun", 3.9840533333e3, speedAggr.getMax(), 1e-7); Assert.assertEquals("Invalid total for sun", 2153734.6966666686, speedAggr.getTotal(), 1e-7); @SuppressWarnings("deprecation") Aggregates weightAggr = fd.getAggregates("shade"); System.out.println(weightAggr.dump()); Assert.assertEquals("Invalid average for shade", 2.0128491560, weightAggr.getAverage(), 1e-7); Assert.assertEquals("Invalid first for shade", 5.9251000000E02, weightAggr.getFirst(), 1e-7); Assert.assertEquals("Invalid last for shade", 5.0486666667E02, weightAggr.getLast(), 1e-7); Assert.assertEquals("Invalid min for shade", 4.4615000000E02, weightAggr.getMin(), 1e-7); Assert.assertEquals("Invalid max for shade", 7.3451666667E02, weightAggr.getMax(), 1e-7); Assert.assertEquals("Invalid total for shade", 361708.99333333364, weightAggr.getTotal(), 1e-7); } @Test public void testBuild1() throws IOException { long start = START; RrdDef rrdDef = new RrdDef(testFolder.newFile("testBuild.rrd").getCanonicalPath(), start - 1, 300); rrdDef.setVersion(1); rrdDef.addDatasource("sun", GAUGE, 600, 0, Double.NaN); rrdDef.addDatasource("shade", GAUGE, 600, 0, Double.NaN); rrdDef.addArchive(AVERAGE, 0.5, 1, 600); rrdDef.addArchive(AVERAGE, 0.5, 6, 700); rrdDef.addArchive(AVERAGE, 0.5, 24, 775); rrdDef.addArchive(AVERAGE, 0.5, 288, 797); rrdDef.addArchive(TOTAL, 0.5, 1, 600); rrdDef.addArchive(TOTAL, 0.5, 6, 700); rrdDef.addArchive(TOTAL, 0.5, 24, 775); rrdDef.addArchive(TOTAL, 0.5, 288, 797); rrdDef.addArchive(MAX, 0.5, 1, 600); rrdDef.addArchive(MAX, 0.5, 6, 700); rrdDef.addArchive(MAX, 0.5, 24, 775); rrdDef.addArchive(MAX, 0.5, 288, 797); RrdDb rrdDb = new RrdDb(rrdDef); testRrdDb(rrdDb); Assert.assertEquals("not expected version", 1, rrdDb.getRrdDef().getVersion()); } @Test public void testBuild2() throws IOException { long start = START; RrdDef rrdDef = new RrdDef(testFolder.newFile("testBuild.rrd").getCanonicalPath(), start - 1, 300); rrdDef.setVersion(2); rrdDef.addDatasource("sun", GAUGE, 600, 0, Double.NaN); rrdDef.addDatasource("shade", GAUGE, 600, 0, Double.NaN); rrdDef.addArchive(AVERAGE, 0.5, 1, 600); rrdDef.addArchive(AVERAGE, 0.5, 6, 700); rrdDef.addArchive(AVERAGE, 0.5, 24, 775); rrdDef.addArchive(AVERAGE, 0.5, 288, 797); rrdDef.addArchive(TOTAL, 0.5, 1, 600); rrdDef.addArchive(TOTAL, 0.5, 6, 700); rrdDef.addArchive(TOTAL, 0.5, 24, 775); rrdDef.addArchive(TOTAL, 0.5, 288, 797); rrdDef.addArchive(MAX, 0.5, 1, 600); rrdDef.addArchive(MAX, 0.5, 6, 700); rrdDef.addArchive(MAX, 0.5, 24, 775); rrdDef.addArchive(MAX, 0.5, 288, 797); RrdDb rrdDb = new RrdDb(rrdDef); testRrdDb(rrdDb); Assert.assertEquals("not expected version", 2, rrdDb.getRrdDef().getVersion()); } @Test public void testRead1() throws IOException { URL url = getClass().getResource("/demo1.rrd"); RrdDb rrd = new RrdDb(url.getFile(), RrdBackendFactory.getFactory("FILE")); testRrdDb(rrd); checkValues(rrd); Assert.assertEquals("not expected version", 1, rrd.getRrdDef().getVersion()); } @Test public void testRead2() throws IOException { URL url = getClass().getResource("/demo2.rrd"); RrdDb rrd = new RrdDb(url.getFile(), RrdBackendFactory.getFactory("FILE")); testRrdDb(rrd); Assert.assertEquals("not expected version", 2, rrd.getRrdDef().getVersion()); checkValues(rrd); } @Test public void testXml1Import() throws IOException { URL url = getClass().getResource("/rrdtool/rrdtool1.xml"); RrdDb rrd = new RrdDb(testFolder.newFile("testxml1import.rrd").getCanonicalPath(), "xml:/" + url.getFile(), RrdBackendFactory.getFactory("FILE")); testRrdDbXml(rrd); } @Test public void testXml3Import() throws IOException { URL url = getClass().getResource("/rrdtool/rrdtool3.xml"); RrdDb rrd = new RrdDb(testFolder.newFile("testxml3import.rrd").getCanonicalPath(), "xml:/" + url.getFile(), RrdBackendFactory.getFactory("FILE")); testRrdDbXml(rrd); } @Test public void testSpike() throws IOException { RrdDef rrdDef = new RrdDef(testFolder.newFile("testSpike.rrd").getCanonicalPath(), 0, 60); rrdDef.setVersion(2); rrdDef.addDatasource("ds", GAUGE, 3600, -5, 30); rrdDef.addArchive(AVERAGE, 0.5, 60, 999); RrdDb rrdDb = new RrdDb(rrdDef); Calendar testTime = Calendar.getInstance(); testTime.set(Calendar.MINUTE, 0); testTime.set(Calendar.SECOND, 0); testTime.set(Calendar.MILLISECOND, 0); System.out.println(testTime); //testTime.add(Calendar.HOUR, -1); long start = Util.getTimestamp(testTime); long timeStamp = start; for(int i = 0; i < 180; i++) { long sampleTime = timeStamp; if(i == 117) { sampleTime += -1; } rrdDb.createSample(sampleTime).setValue("ds", 30).update(); timeStamp += 60; } long end = timeStamp; FetchData f = rrdDb.createFetchRequest(AVERAGE, start, end).fetchData(); System.out.println(f.dump()); double[] values = f.getValues("ds"); Assert.assertEquals("Data before first entry", Double.NaN, values[0], 0.0); Assert.assertEquals("Bad average in point 1", 30, values[1], 1e-3); Assert.assertEquals("Bad average in point 2", 30, values[2], 1e-3); Assert.assertEquals("Data after last entry", Double.NaN, values[3], 0.0); } }