Changeset 19671 in josm


Ignore:
Timestamp:
2026-11-01T20:49:00+01:00 (8 hours ago)
Author:
gaben
Message:

fix #22878 - ConcurrentModificationException in MapCSSTagChecker when the rules are reloaded during validation

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

    r19629 r19671  
    405405     */
    406406    void visit(Collection<OsmPrimitive> selection, Predicate<String> urlPredicate) {
     407        // the rules may be reloaded by another thread (preferences, file watcher) while the validation is running, see #22878
     408        final List<Entry<String, Set<MapCSSTagCheckerRule>>> checksToRun;
     409        synchronized (this) {
     410            checksToRun = new ArrayList<>(checks.entrySet());
     411        }
    407412        if (urlPredicate == null && progressMonitor != null) {
    408             progressMonitor.setTicksCount(selection.size() * checks.size());
     413            progressMonitor.setTicksCount(selection.size() * checksToRun.size());
    409414        }
    410415
    … …  
    414419
    415420        Set<OsmPrimitive> surrounding = new HashSet<>();
    416         for (Entry<String, Set<MapCSSTagCheckerRule>> entry : checks.entrySet()) {
     421        for (Entry<String, Set<MapCSSTagCheckerRule>> entry : checksToRun) {
    417422            if (isCanceled()) {
    418423                break;
  • trunk/test/unit/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerTest.java

    r18921 r19671  
    478478        assertTrue(test.getErrors().isEmpty());
    479479    }
     480
     481    /**
     482     * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/22878">#22878</a>
     483     * - rules reloaded while the validation is running.
     484     * @throws ParseException if a parsing error occurs
     485     */
     486    @Test
     487    void testTicket22878() throws ParseException {
     488        final MapCSSTagChecker test = buildTagChecker("node[amenity=bench] { throwWarning: \"bench\"; }");
     489        final String css = "node[amenity=bench] { throwWarning: \"other bench\"; }";
     490        test.checks.putAll("other", MapCSSTagCheckerRule.readMapCSS(new StringReader(css)).parseChecks);
     491        final OsmPrimitive p = OsmUtils.createPrimitive("node amenity=bench");
     492        new DataSet(p);
     493        test.startTest(NullProgressMonitor.INSTANCE);
     494        // the predicate is called while iterating over the rules, reload them there like addMapCSS does
     495        assertDoesNotThrow(() -> test.visit(List.of(p), url -> {
     496            try {
     497                test.checks.remove("other");
     498                test.checks.putAll("other", MapCSSTagCheckerRule.readMapCSS(new StringReader(css)).parseChecks);
     499            } catch (ParseException e) {
     500                throw new IllegalStateException(e);
     501            }
     502            return true;
     503        }));
     504        test.endTest();
     505        assertTrue(test.getErrors().stream().anyMatch(e -> "bench".equals(e.getMessage())));
     506    }
    480507}
Note: See TracChangeset for help on using the changeset viewer.