SOLR-11779: Improve stability of this test - use predictable timestamps and avoid sampling races.

This commit is contained in:
Andrzej Bialecki 2018-06-11 12:22:18 +02:00
parent 0242409fae
commit 16e0c234ed
1 changed files with 42 additions and 25 deletions

View File

@ -17,14 +17,16 @@
package org.apache.solr.metrics.rrd; package org.apache.solr.metrics.rrd;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.Map;
import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.CollectionAdminParams; import org.apache.solr.common.params.CollectionAdminParams;
import org.apache.solr.common.util.Pair; import org.apache.solr.common.util.Pair;
import org.apache.solr.common.util.TimeSource; import org.apache.solr.common.util.TimeSource;
import org.apache.solr.common.util.Utils;
import org.apache.solr.util.MockSearchableSolrClient; import org.apache.solr.util.MockSearchableSolrClient;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -64,8 +66,9 @@ public class SolrRrdBackendFactoryTest extends SolrTestCaseJ4 {
} }
} }
private RrdDef createDef() { private RrdDef createDef(long startTime) {
RrdDef def = new RrdDef("solr:foo", 60); RrdDef def = new RrdDef("solr:foo", 60);
def.setStartTime(startTime);
def.addDatasource("one", DsType.COUNTER, 120, Double.NaN, Double.NaN); def.addDatasource("one", DsType.COUNTER, 120, Double.NaN, Double.NaN);
def.addDatasource("two", DsType.GAUGE, 120, Double.NaN, Double.NaN); def.addDatasource("two", DsType.GAUGE, 120, Double.NaN, Double.NaN);
def.addArchive(ConsolFun.AVERAGE, 0.5, 1, 120); // 2 hours def.addArchive(ConsolFun.AVERAGE, 0.5, 1, 120); // 2 hours
@ -77,7 +80,8 @@ public class SolrRrdBackendFactoryTest extends SolrTestCaseJ4 {
@Test @Test
public void testBasic() throws Exception { public void testBasic() throws Exception {
RrdDb db = new RrdDb(createDef(), factory); long startTime = 1000000000;
RrdDb db = new RrdDb(createDef(startTime), factory);
List<Pair<String, Long>> list = factory.list(100); List<Pair<String, Long>> list = factory.list(100);
assertEquals(list.toString(), 1, list.size()); assertEquals(list.toString(), 1, list.size());
assertEquals(list.toString(), "foo", list.get(0).first()); assertEquals(list.toString(), "foo", list.get(0).first());
@ -90,36 +94,38 @@ public class SolrRrdBackendFactoryTest extends SolrTestCaseJ4 {
timeSource.sleep(2000); timeSource.sleep(2000);
SolrInputDocument newDoc = solrClient.docs.get(CollectionAdminParams.SYSTEM_COLL).get(id); SolrInputDocument newDoc = solrClient.docs.get(CollectionAdminParams.SYSTEM_COLL).get(id);
assertEquals(newDoc.toString(), newDoc, doc); assertEquals(newDoc.toString(), newDoc, doc);
long firstTimestamp = TimeUnit.SECONDS.convert(timestamp, TimeUnit.MILLISECONDS); // make sure the update doesn't race with the sampling boundaries
long lastTimestamp = firstTimestamp + 60; long lastTime = startTime + 30;
// update the db // update the db
Sample s = db.createSample(); Sample s = db.createSample();
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
s.setTime(lastTimestamp); s.setTime(lastTime);
s.setValue("one", 1000 + i * 60); s.setValue("one", 1000 + i * 60);
s.setValue("two", 100); s.setValue("two", 100);
s.update(); s.update();
lastTimestamp = lastTimestamp + 60; lastTime = lastTime + 60;
} }
timeSource.sleep(3000); timeSource.sleep(3000);
newDoc = solrClient.docs.get(CollectionAdminParams.SYSTEM_COLL).get(id); newDoc = solrClient.docs.get(CollectionAdminParams.SYSTEM_COLL).get(id);
assertFalse(newDoc.toString(), newDoc.equals(doc)); assertFalse(newDoc.toString(), newDoc.equals(doc));
long newTimestamp = (Long)newDoc.getFieldValue("timestamp_l"); long newTimestamp = (Long)newDoc.getFieldValue("timestamp_l");
assertNotSame(newTimestamp, timestamp); assertNotSame(newTimestamp, timestamp);
FetchRequest fr = db.createFetchRequest(ConsolFun.AVERAGE, firstTimestamp + 60, lastTimestamp - 60, 60); // don't race with the sampling boundary
FetchRequest fr = db.createFetchRequest(ConsolFun.AVERAGE, startTime + 20, lastTime - 20, 60);
FetchData fd = fr.fetchData(); FetchData fd = fr.fetchData();
int rowCount = fd.getRowCount(); int rowCount = fd.getRowCount();
double[] one = fd.getValues("one"); double[] one = fd.getValues("one");
assertEquals("one", 101, one.length);
assertEquals(Double.NaN, one[0], 0.00001);
assertEquals(Double.NaN, one[100], 0.00001);
for (int i = 1; i < 100; i++) {
assertEquals(1.0, one[i], 0.00001);
}
double[] two = fd.getValues("two"); double[] two = fd.getValues("two");
assertEquals(Double.NaN, two[100], 0.00001); String dump = dumpData(db, fd);
assertEquals("one: " + dump, 101, one.length);
assertEquals(dump, Double.NaN, one[0], 0.00001);
assertEquals(dump, Double.NaN, one[100], 0.00001);
for (int i = 1; i < 100; i++) { for (int i = 1; i < 100; i++) {
assertEquals("wrong value at pos " + i, 100.0, two[i], 0.00001); assertEquals(dump + "\npos=" + i, 1.0, one[i], 0.00001);
}
assertEquals("two: " + dump, Double.NaN, two[100], 0.00001);
for (int i = 0; i < 100; i++) {
assertEquals(dump + "\ntwo pos=" + i, 100.0, two[i], 0.00001);
} }
db.close(); db.close();
@ -131,7 +137,7 @@ public class SolrRrdBackendFactoryTest extends SolrTestCaseJ4 {
// re-open read-write // re-open read-write
db = new RrdDb("solr:foo", factory); db = new RrdDb("solr:foo", factory);
s = db.createSample(); s = db.createSample();
s.setTime(lastTimestamp); s.setTime(lastTime);
s.setValue("one", 7000); s.setValue("one", 7000);
s.setValue("two", 100); s.setValue("two", 100);
s.update(); s.update();
@ -143,20 +149,21 @@ public class SolrRrdBackendFactoryTest extends SolrTestCaseJ4 {
assertFalse(newDoc.toString(), newDoc.equals(doc)); assertFalse(newDoc.toString(), newDoc.equals(doc));
newTimestamp = (Long)newDoc.getFieldValue("timestamp_l"); newTimestamp = (Long)newDoc.getFieldValue("timestamp_l");
assertNotSame(newTimestamp, timestamp); assertNotSame(newTimestamp, timestamp);
fr = db.createFetchRequest(ConsolFun.AVERAGE, firstTimestamp + 60, lastTimestamp, 60); fr = db.createFetchRequest(ConsolFun.AVERAGE, startTime + 20, lastTime + 20, 60);
fd = fr.fetchData(); fd = fr.fetchData();
dump = dumpData(db, fd);
rowCount = fd.getRowCount(); rowCount = fd.getRowCount();
one = fd.getValues("one"); one = fd.getValues("one");
assertEquals("one", 102, one.length); assertEquals("one: " + dump, 102, one.length);
assertEquals(Double.NaN, one[0], 0.00001); assertEquals(dump, Double.NaN, one[0], 0.00001);
assertEquals(Double.NaN, one[101], 0.00001); assertEquals(dump, Double.NaN, one[101], 0.00001);
for (int i = 1; i < 101; i++) { for (int i = 1; i < 101; i++) {
assertEquals(1.0, one[i], 0.00001); assertEquals(dump, 1.0, one[i], 0.00001);
} }
two = fd.getValues("two"); two = fd.getValues("two");
assertEquals(Double.NaN, two[101], 0.00001); assertEquals("two: " + dump, Double.NaN, two[101], 0.00001);
for (int i = 1; i < 101; i++) { for (int i = 1; i < 101; i++) {
assertEquals(100.0, two[i], 0.00001); assertEquals(dump, 100.0, two[i], 0.00001);
} }
db.close(); db.close();
@ -164,7 +171,7 @@ public class SolrRrdBackendFactoryTest extends SolrTestCaseJ4 {
// open a read-only version of the db // open a read-only version of the db
RrdDb readOnly = new RrdDb("solr:foo", true, factory); RrdDb readOnly = new RrdDb("solr:foo", true, factory);
s = readOnly.createSample(); s = readOnly.createSample();
s.setTime(lastTimestamp + 120); s.setTime(lastTime + 120);
s.setValue("one", 10000001); s.setValue("one", 10000001);
s.setValue("two", 100); s.setValue("two", 100);
s.update(); s.update();
@ -179,4 +186,14 @@ public class SolrRrdBackendFactoryTest extends SolrTestCaseJ4 {
readOnly.close(); readOnly.close();
} }
private String dumpData(RrdDb db, FetchData fd) throws Exception {
Map<String, Object> map = new LinkedHashMap<>();
map.put("dbLastUpdateTime", db.getLastUpdateTime());
map.put("firstTimestamp", fd.getFirstTimestamp());
map.put("lastTimestamp", fd.getLastTimestamp());
map.put("timestamps", fd.getTimestamps());
map.put("data", fd.dump());
return Utils.toJSONString(map);
}
} }