Ticket #13240: patch-test-mapcss-condition.patch
| File patch-test-mapcss-condition.patch, 20.9 KB (added by , 10 years ago) |
|---|
-
src/org/openstreetmap/josm/data/osm/OsmUtils.java
diff --git a/src/org/openstreetmap/josm/data/osm/OsmUtils.java b/src/org/openstreetmap/josm/data/osm/OsmUtils.java index 9e7a9dd..62de4ed 100644
a b public final class OsmUtils { 74 74 if (p == null) { 75 75 throw new IllegalArgumentException("Expecting n/node/w/way/r/relation/area, but got '" + x[0] + '\''); 76 76 } 77 for (final Map.Entry<String, String> i : TextTagParser.readTagsFromText(x[1]).entrySet()) { 78 p.put(i.getKey(), i.getValue()); 77 if (x.length > 1) { 78 for (final Map.Entry<String, String> i : TextTagParser.readTagsFromText(x[1]).entrySet()) { 79 p.put(i.getKey(), i.getValue()); 80 } 79 81 } 80 82 return p; 81 83 } -
test/performance/org/openstreetmap/josm/PerformanceTestUtils.java
diff --git a/test/performance/org/openstreetmap/josm/PerformanceTestUtils.java b/test/performance/org/openstreetmap/josm/PerformanceTestUtils.java index d1deee9..c7ec73a 100644
a b 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm; 3 3 4 import java.util.ArrayList; 5 import java.util.Collections; 6 4 7 import org.openstreetmap.josm.io.XmlWriter; 5 8 6 9 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; … … import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 10 13 * @author Michael Zangl 11 14 */ 12 15 public final class PerformanceTestUtils { 16 private static final int TIMES_WARMUP = 2; 17 private static final int TIMES_RUN = 8; 18 19 /** 20 * A helper class that captures the time from object creation until #done() was called. 21 * @author Michael Zangl 22 * @since xxx 23 */ 24 public static class PerformanceTestTimerCapture { 25 private final long time; 26 27 protected PerformanceTestTimerCapture() { 28 time = System.nanoTime(); 29 } 30 31 /** 32 * Get the time since this object was created. 33 * @return The time. 34 */ 35 public long getTimeSinceCreation() { 36 return (System.nanoTime() - time) / 1000000; 37 } 38 } 13 39 /** 14 40 * A timer that measures the time from it's creation to the {@link #done()} call. 15 41 * @author Michael Zangl 16 42 */ 17 public static class PerformanceTestTimer {43 public static class PerformanceTestTimer extends PerformanceTestTimerCapture { 18 44 private final String name; 19 private final long time; 20 private boolean measurementPlotsPlugin = false; 45 private boolean measurementPlotsPlugin = true; 21 46 22 47 protected PerformanceTestTimer(String name) { 23 48 this.name = name; 24 time = System.nanoTime();25 49 } 26 50 27 51 /** … … public final class PerformanceTestUtils { 36 60 * Prints the time since this timer was created. 37 61 */ 38 62 public void done() { 39 long dTime = (System.nanoTime() - time) / 1000000;63 long dTime = getTimeSinceCreation(); 40 64 if (measurementPlotsPlugin) { 41 65 measurementPlotsPluginOutput(name + "(ms)", dTime); 42 66 } else { … … public final class PerformanceTestUtils { 45 69 } 46 70 } 47 71 72 48 73 private PerformanceTestUtils() { 49 74 } 50 75 51 76 /** 52 * Starts a new performance timer. 77 * Starts a new performance timer. The timer will output the measurements in a format understood by Jenkins. 78 * <p> 79 * The timer can only be used to meassure one value. 53 80 * @param name The name/description of the timer. 54 81 * @return A {@link PerformanceTestTimer} object of which you can call {@link PerformanceTestTimer#done()} when done. 55 82 */ 56 83 @SuppressFBWarnings(value = "DM_GC", justification = "Performance test code") 57 84 public static PerformanceTestTimer startTimer(String name) { 85 cleanSystem(); 86 return new PerformanceTestTimer(name); 87 } 88 89 /** 90 * Runs the given performance test several (approx. 10) times and prints the median run time. 91 * @param name The name to use in the output 92 * @param testRunner The test to run 93 */ 94 public static void runPerformanceTest(String name, Runnable testRunner) { 95 for (int i = 0; i < TIMES_WARMUP; i++) { 96 cleanSystem(); 97 PerformanceTestTimerCapture capture = new PerformanceTestTimerCapture(); 98 testRunner.run(); 99 capture.getTimeSinceCreation(); 100 } 101 ArrayList<Long> times = new ArrayList<>(); 102 for (int i = 0; i < TIMES_RUN; i++) { 103 cleanSystem(); 104 PerformanceTestTimerCapture capture = new PerformanceTestTimerCapture(); 105 testRunner.run(); 106 times.add(capture.getTimeSinceCreation()); 107 } 108 System.out.println(times); 109 Collections.sort(times); 110 // Sort out e.g. GC during test run. 111 double avg = times.subList(2, times.size() - 2).stream().mapToLong(l -> l).average().getAsDouble(); 112 measurementPlotsPluginOutput(name, avg); 113 } 114 115 private static void cleanSystem() { 58 116 System.gc(); 59 117 System.runFinalization(); 60 return new PerformanceTestTimer(name);61 118 } 62 119 63 120 /** … … public final class PerformanceTestUtils { 67 124 * 68 125 * @param name the name / title of the measurement 69 126 * @param value the value 70 * @see https://wiki.jenkins-ci.org/display/JENKINS/Measurement+Plots+Plugin127 * @see "https://wiki.jenkins-ci.org/display/JENKINS/Measurement+Plots+Plugin" 71 128 */ 72 129 public static void measurementPlotsPluginOutput(String name, double value) { 73 130 System.err.println("<measurement><name>"+XmlWriter.encode(name)+"</name><value>"+value+"</value></measurement>"); -
new file test/performance/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSConditionPerformanceTest.java
diff --git a/test/performance/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSConditionPerformanceTest.java b/test/performance/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSConditionPerformanceTest.java new file mode 100644 index 0000000..97ff6fe
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.mappaint.mapcss; 3 4 import java.util.EnumSet; 5 6 import org.junit.Test; 7 import org.openstreetmap.josm.PerformanceTestUtils; 8 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Op; 9 10 /** 11 * Performance test of MapCSS Condition objects. 12 * @author Michael Zangl 13 * @since xxx 14 */ 15 public class MapCSSConditionPerformanceTest { 16 /** 17 * Test the performance of all OP entries. 18 */ 19 @Test 20 public void testAllOps() { 21 // The JIT does some really heavy optimisations if it notices that other values are not used. 22 // If we want to simulate a real scenario, we need to invoke every op several times to let the compiler 23 // build the jump tables. 24 for (Op op : Op.values()) { 25 getRunner(op).run(); 26 } 27 for (Op op : Op.values()) { 28 runTest(op); 29 } 30 } 31 32 private void runTest(Op op) { 33 Runnable r = getRunner(op); 34 PerformanceTestUtils.runPerformanceTest("Condition.Op." + op, r); 35 } 36 37 private Runnable getRunner(Op op) { 38 Runnable r; 39 if (EnumSet.of(Op.LESS, Op.LESS_OR_EQUAL, Op.GREATER, Op.GREATER_OR_EQUAL).contains(op)) { 40 r = () -> { 41 for (int i = 0; i < 10000; i++) { 42 op.eval(null, "0.2"); 43 op.eval("nan", "0.1"); 44 op.eval("0.2983", "192.312"); 45 op.eval("0.2983", "0.2983"); 46 op.eval("2983", "1000"); 47 op.eval("1000", "1000"); 48 } 49 }; 50 } else { 51 // regexp are slow 52 int runs = EnumSet.of(Op.ONE_OF, Op.REGEX, Op.NREGEX).contains(op) ? 10000 : 100000; 53 r = () -> { 54 for (int i = 0; i < runs; i++) { 55 op.eval("k1", "v1"); 56 op.eval("k1", "k1"); 57 op.eval("", "v1"); 58 op.eval(null, "abc"); 59 op.eval("extreamlylongkeyextreamlylongkeyextreamlylongkeyextreamlylongkey", 60 "longvaluelongvaluelongvaluelongvalue"); 61 op.eval("0.2983", "192.312"); 62 op.eval("0.2983", "0.2983"); 63 op.eval("2983", "\\d+"); 64 } 65 }; 66 } 67 return r; 68 } 69 } -
test/performance/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSourceFilterTest.java
diff --git a/test/performance/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSourceFilterTest.java b/test/performance/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSourceFilterTest.java index 9f7a24a..424a73f 100644
a b public class MapCSSStyleSourceFilterTest { 103 103 KeyValueDataGenerator data = OsmDataGenerator.getKeyValue(); 104 104 data.generateDataSet(); 105 105 CssGenerator css = new CssGenerator(data).addKeyValueRules(TEST_RULE_COUNT); 106 runTest(data, css, "only key=value rules" , false);106 runTest(data, css, "only key=value rules"); 107 107 } 108 108 109 109 /** … … public class MapCSSStyleSourceFilterTest { 114 114 KeyValueDataGenerator data = OsmDataGenerator.getKeyValue(); 115 115 data.generateDataSet(); 116 116 CssGenerator css = new CssGenerator(data).addHasKeyRules(TEST_RULE_COUNT); 117 runTest(data, css, "only has key rules" , false);117 runTest(data, css, "only has key rules"); 118 118 } 119 119 120 120 /** … … public class MapCSSStyleSourceFilterTest { 125 125 KeyValueDataGenerator data = OsmDataGenerator.getKeyValue(); 126 126 data.generateDataSet(); 127 127 CssGenerator css = new CssGenerator(data).addKeyRegexpRules(TEST_RULE_COUNT); 128 runTest(data, css, "regular expressions" , true);128 runTest(data, css, "regular expressions"); 129 129 } 130 130 131 131 /** … … public class MapCSSStyleSourceFilterTest { 136 136 KeyValueDataGenerator data = OsmDataGenerator.getKeyValue(); 137 137 data.generateDataSet(); 138 138 CssGenerator css = new CssGenerator(data).addIsTrueRules(TEST_RULE_COUNT); 139 runTest(data, css, "is true" , false);139 runTest(data, css, "is true"); 140 140 } 141 141 142 private void runTest(KeyValueDataGenerator data, CssGenerator css, String description , boolean measurementPlotsPlugin) {142 private void runTest(KeyValueDataGenerator data, CssGenerator css, String description) { 143 143 MapCSSStyleSource source = new MapCSSStyleSource(css.getCss()); 144 144 PerformanceTestTimer timer = PerformanceTestUtils.startTimer("MapCSSStyleSource#loadStyleSource(...) for " + description); 145 145 source.loadStyleSource(); 146 146 timer.done(); 147 147 148 if (measurementPlotsPlugin) { 149 timer = PerformanceTestUtils.startTimer(description); 150 timer.setMeasurementPlotsPluginOutput(true); 151 } else { 152 timer = PerformanceTestUtils.startTimer(APPLY_CALLS + "x MapCSSStyleSource#apply(...) for " + description); 153 } 148 timer = PerformanceTestUtils.startTimer(APPLY_CALLS + "x MapCSSStyleSource#apply(...) for " + description); 154 149 for (int i = 0; i < APPLY_CALLS; i++) { 155 150 MultiCascade mc = new MultiCascade(); 156 151 source.apply(mc, data.randomNode(), 1, false); -
new file test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionTest.java
diff --git a/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionTest.java b/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionTest.java new file mode 100644 index 0000000..4ebe152
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.mappaint.mapcss; 3 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertFalse; 6 import static org.junit.Assert.assertTrue; 7 8 import org.junit.Before; 9 import org.junit.Rule; 10 import org.junit.Test; 11 import org.openstreetmap.josm.data.osm.OsmPrimitive; 12 import org.openstreetmap.josm.data.osm.OsmUtils; 13 import org.openstreetmap.josm.gui.mappaint.Environment; 14 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context; 15 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Op; 16 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.SimpleKeyValueCondition; 17 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.ToTagConvertable; 18 import org.openstreetmap.josm.testutils.JOSMTestRules; 19 20 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 21 22 /** 23 * This test universally tests all {@link Condition}s. 24 * @author Michael Zangl 25 * @since xxx 26 */ 27 public class ConditionTest { 28 /** 29 * We need prefs for nodes. 30 */ 31 @Rule 32 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 33 public JOSMTestRules test = new JOSMTestRules().preferences(); 34 private OsmPrimitive node0; 35 private OsmPrimitive node1; 36 private OsmPrimitive node2; 37 private OsmPrimitive node3; 38 private OsmPrimitive node4; 39 40 /** 41 * Set up some useful test data. 42 */ 43 @Before 44 public void setUp() { 45 node0 = OsmUtils.createPrimitive("n"); 46 node1 = OsmUtils.createPrimitive("n k1=v1 k2=v1 f1=0.2 r1=ababx c1=xya one=a;b"); 47 node2 = OsmUtils.createPrimitive("n k1=v1 k2=v1a f1=0.8 r1=abxabxab c1=xy one=a;;x"); 48 node3 = OsmUtils.createPrimitive("n k1=v1 f1=-100 c1=axy one=x;y;z"); 49 node4 = OsmUtils.createPrimitive("n k1=v2a k2=v3 f1=x r1=abab c1=axya one=x;a;y"); 50 } 51 52 /** 53 * Test {@link Op#EQ}. 54 */ 55 @Test 56 public void testKeyValueEq() { 57 Condition op = Condition.createKeyValueCondition("k1", "v1", Op.EQ, Context.PRIMITIVE, false); 58 assertFalse(op.applies(genEnv(node0))); 59 assertTrue(op.applies(genEnv(node1))); 60 assertTrue(op.applies(genEnv(node2))); 61 assertTrue(op.applies(genEnv(node3))); 62 assertFalse(op.applies(genEnv(node4))); 63 64 assertTrue(op instanceof SimpleKeyValueCondition); 65 assertEquals("[k1=v1]", op.toString()); 66 assertEquals("k1", ((ToTagConvertable) op).asTag(null).getKey()); 67 assertEquals("v1", ((ToTagConvertable) op).asTag(null).getValue()); 68 } 69 70 /** 71 * Test {@link Op#EQ} and interpetation as key 72 */ 73 @Test 74 public void testKeyValueEqAsKey() { 75 Condition op = Condition.createKeyValueCondition("k1", "k2", Op.EQ, Context.PRIMITIVE, true); 76 assertFalse(op.applies(genEnv(node0))); 77 assertTrue(op.applies(genEnv(node1))); 78 assertFalse(op.applies(genEnv(node2))); 79 assertFalse(op.applies(genEnv(node3))); 80 assertFalse(op.applies(genEnv(node4))); 81 82 assertEquals("k1", ((ToTagConvertable) op).asTag(null).getKey()); 83 assertEquals("k2", ((ToTagConvertable) op).asTag(null).getValue()); 84 } 85 /** 86 * Test {@link Op#NEQ} 87 */ 88 @Test 89 public void testKeyValueNeq() { 90 Condition op = Condition.createKeyValueCondition("k1", "v1", Op.NEQ, Context.PRIMITIVE, false); 91 assertTrue(op.applies(genEnv(node0))); 92 assertFalse(op.applies(genEnv(node1))); 93 assertFalse(op.applies(genEnv(node2))); 94 assertFalse(op.applies(genEnv(node3))); 95 assertTrue(op.applies(genEnv(node4))); 96 } 97 98 /** 99 * Test {@link Op#GREATER_OR_EQUAL} 100 */ 101 @Test 102 public void testKeyValueGreatherEq() { 103 Condition op = Condition.createKeyValueCondition("f1", "0.2", Op.GREATER_OR_EQUAL, Context.PRIMITIVE, false); 104 assertFalse(op.applies(genEnv(node0))); 105 assertTrue(op.applies(genEnv(node1))); 106 assertTrue(op.applies(genEnv(node2))); 107 assertFalse(op.applies(genEnv(node3))); 108 assertFalse(op.applies(genEnv(node4))); 109 } 110 111 /** 112 * Test {@link Op#GREATER} 113 */ 114 @Test 115 public void testKeyValueGreather() { 116 Condition op = Condition.createKeyValueCondition("f1", "0.2", Op.GREATER, Context.PRIMITIVE, false); 117 assertFalse(op.applies(genEnv(node0))); 118 assertFalse(op.applies(genEnv(node1))); 119 assertTrue(op.applies(genEnv(node2))); 120 assertFalse(op.applies(genEnv(node3))); 121 assertFalse(op.applies(genEnv(node4))); 122 } 123 124 /** 125 * Test {@link Op#LESS_OR_EQUAL} 126 */ 127 @Test 128 public void testKeyValueLessEq() { 129 Condition op = Condition.createKeyValueCondition("f1", "0.2", Op.LESS_OR_EQUAL, Context.PRIMITIVE, false); 130 assertFalse(op.applies(genEnv(node0))); 131 assertTrue(op.applies(genEnv(node1))); 132 assertFalse(op.applies(genEnv(node2))); 133 assertTrue(op.applies(genEnv(node3))); 134 assertFalse(op.applies(genEnv(node4))); 135 } 136 137 /** 138 * Test {@link Op#LESS} 139 */ 140 @Test 141 public void testKeyValueLess() { 142 Condition op = Condition.createKeyValueCondition("f1", "0.2", Op.LESS, Context.PRIMITIVE, false); 143 assertFalse(op.applies(genEnv(node0))); 144 assertFalse(op.applies(genEnv(node1))); 145 assertFalse(op.applies(genEnv(node2))); 146 assertTrue(op.applies(genEnv(node3))); 147 assertFalse(op.applies(genEnv(node4))); 148 } 149 150 /** 151 * Test {@link Op#REGEX} 152 */ 153 @Test 154 public void testKeyValueRegex() { 155 Condition op = Condition.createKeyValueCondition("r1", "(ab){2}", Op.REGEX, Context.PRIMITIVE, false); 156 assertFalse(op.applies(genEnv(node0))); 157 assertTrue(op.applies(genEnv(node1))); 158 assertFalse(op.applies(genEnv(node2))); 159 assertFalse(op.applies(genEnv(node3))); 160 assertTrue(op.applies(genEnv(node4))); 161 } 162 163 /** 164 * Test {@link Op#NREGEX} 165 */ 166 @Test 167 public void testKeyValueNregex() { 168 Condition op = Condition.createKeyValueCondition("r1", "(ab){2}", Op.NREGEX, Context.PRIMITIVE, false); 169 assertTrue(op.applies(genEnv(node0))); 170 assertFalse(op.applies(genEnv(node1))); 171 assertTrue(op.applies(genEnv(node2))); 172 assertTrue(op.applies(genEnv(node3))); 173 assertFalse(op.applies(genEnv(node4))); 174 } 175 176 /** 177 * Test {@link Op#ONE_OF} 178 */ 179 @Test 180 public void testKeyValueOneOf() { 181 Condition op = Condition.createKeyValueCondition("one", "a", Op.ONE_OF, Context.PRIMITIVE, false); 182 assertFalse(op.applies(genEnv(node0))); 183 assertTrue(op.applies(genEnv(node1))); 184 assertTrue(op.applies(genEnv(node2))); 185 assertFalse(op.applies(genEnv(node3))); 186 assertTrue(op.applies(genEnv(node4))); 187 } 188 189 /** 190 * Test {@link Op#BEGINS_WITH} 191 */ 192 @Test 193 public void testKeyValueBeginsWith() { 194 Condition op = Condition.createKeyValueCondition("c1", "xy", Op.BEGINS_WITH, Context.PRIMITIVE, false); 195 assertFalse(op.applies(genEnv(node0))); 196 assertTrue(op.applies(genEnv(node1))); 197 assertTrue(op.applies(genEnv(node2))); 198 assertFalse(op.applies(genEnv(node3))); 199 assertFalse(op.applies(genEnv(node4))); 200 } 201 202 /** 203 * Test {@link Op#ENDS_WITH} 204 */ 205 @Test 206 public void testKeyValueEndsWith() { 207 Condition op = Condition.createKeyValueCondition("c1", "xy", Op.ENDS_WITH, Context.PRIMITIVE, false); 208 assertFalse(op.applies(genEnv(node0))); 209 assertFalse(op.applies(genEnv(node1))); 210 assertTrue(op.applies(genEnv(node2))); 211 assertTrue(op.applies(genEnv(node3))); 212 assertFalse(op.applies(genEnv(node4))); 213 } 214 215 /** 216 * Test {@link Op#CONTAINS} 217 */ 218 @Test 219 public void testKeyValueContains() { 220 Condition op = Condition.createKeyValueCondition("c1", "xy", Op.CONTAINS, Context.PRIMITIVE, false); 221 assertFalse(op.applies(genEnv(node0))); 222 assertTrue(op.applies(genEnv(node1))); 223 assertTrue(op.applies(genEnv(node2))); 224 assertTrue(op.applies(genEnv(node3))); 225 assertTrue(op.applies(genEnv(node4))); 226 } 227 228 /** 229 * Test of {@link Condition#createRegexpKeyRegexpValueCondition(String, String, Op)} 230 */ 231 @Test 232 public void testRegexpKeyValueRegexpCondition() { 233 Condition op = Condition.createRegexpKeyRegexpValueCondition("^k", "\\da", Op.REGEX); 234 assertFalse(op.applies(genEnv(node0))); 235 assertFalse(op.applies(genEnv(node1))); 236 assertTrue(op.applies(genEnv(node2))); 237 assertFalse(op.applies(genEnv(node3))); 238 assertTrue(op.applies(genEnv(node4))); 239 240 Condition notOp = Condition.createRegexpKeyRegexpValueCondition("^k", "\\da", Op.NREGEX); 241 assertTrue(notOp.applies(genEnv(node0))); 242 assertTrue(notOp.applies(genEnv(node1))); 243 assertFalse(notOp.applies(genEnv(node2))); 244 assertTrue(notOp.applies(genEnv(node3))); 245 assertFalse(notOp.applies(genEnv(node4))); 246 } 247 248 private Environment genEnv(OsmPrimitive primitive) { 249 return new Environment(primitive); 250 } 251 }
