Ticket #8687: patch_8687_5.diff

File patch_8687_5.diff, 12.1 KB (added by dommage, 11 years ago)

JUnit test first version.

  • src/org/openstreetmap/josm/data/validation/tests/TagChecker.java

     
    761761
    762762    protected static class CheckerData {
    763763        private String description;
    764         private List<CheckerElement> data = new ArrayList<CheckerElement>();
     764        protected List<CheckerElement> data = new ArrayList<CheckerElement>();
    765765        private OsmPrimitiveType type;
    766766        private int code;
    767767        protected Severity severity;
     
    769769        protected static final int TAG_CHECK_WARN   = 1260;
    770770        protected static final int TAG_CHECK_INFO   = 1270;
    771771
    772         private static class CheckerElement {
     772        protected static class CheckerElement {
    773773            public Object tag;
    774774            public Object value;
    775775            public boolean noMatch;
  • data/tagchecker.cfg

     
    179179* : E : wikipedia == * && wikipedia != /[a-zA-Z_-]{2,12}:.*/ # no wikipedia-language given, use ''wikipedia''=''language:page title''
    180180# Valid languages are extracted from <http://de.wikipedia.org/w/api.php?action=sitematrix&format=xml>, which may change, so this is a warning only.
    181181* : W : wikipedia == /[a-zA-Z_-]{2,12}:.*/ && wikipedia != /(aa|ab|ace|af|ak|als|am|an|ang|ar|arc|arz|as|ast|av|ay|az|ba|bar|bat-smg|bcl|be|be-x-old|bg|bh|bi|bjn|bm|bn|bo|bpy|br|bs|bug|bxr|ca|cbk-zam|cdo|ce|ceb|ch|cho|chr|chy|ckb|co|cr|crh|cs|csb|cu|cv|cy|cz|da|de|diq|dk|dsb|dv|dz|ee|el|eml|en|eo|epo|es|et|eu|ext|fa|ff|fi|fiu-vro|fj|fo|fr|frp|frr|fur|fy|ga|gag|gan|gd|gl|glk|gn|got|gu|gv|ha|hak|haw|he|hi|hif|ho|hr|hsb|ht|hu|hy|hz|ia|id|ie|ig|ii|ik|ilo|io|is|it|iu|ja|jbo|jp|jv|ka|kaa|kab|kbd|kg|ki|kj|kk|kl|km|kn|ko|koi|kr|krc|ks|ksh|ku|kv|kw|ky|la|lad|lb|lbe|lez|lg|li|lij|lmo|ln|lo|lt|ltg|lv|map-bms|mdf|mg|mh|mhr|mi|minnan|mk|ml|mn|mo|mr|mrj|ms|mt|mus|mwl|my|myv|mzn|na|nah|nan|nap|nb|nds|nds-nl|ne|new|ng|nl|nn|no|nov|nrm|nso|nv|ny|oc|om|or|os|pa|pag|pam|pap|pcd|pdc|pfl|pi|pih|pl|pms|pnb|pnt|ps|pt|qu|rm|rmy|rn|ro|roa-rup|roa-tara|ru|rue|rw|sa|sah|sc|scn|sco|sd|se|sg|sh|si|simple|sk|sl|sm|sn|so|sq|sr|srn|ss|st|stq|su|sv|sw|szl|ta|te|tet|tg|th|ti|tk|tl|tn|to|tpi|tr|ts|tt|tum|tw|ty|udm|ug|uk|ur|uz|ve|vec|vep|vi|vls|vo|wa|war|wo|wuu|xal|xh|xmf|yi|yo|za|zea|zh|zh-cfr|zh-classical|zh-min-nan|zh-yue|zu):.*/  # unkown language prefix in wikipedia tag
     182
     183# measurement values and units warnings (ticket #8687)
     184way : W : layer == * && layer != /^0$|^-?[1-5]$/  # layer should be between -5 and 5
     185*   : W : level == * && level != /^((([0-9]|-[1-9])|[1-9][0-9]*)(\.5)?)(;(([0-9]|-[1-9])|[1-9][0-9]*)(\.5)?)*$|^-0\.5$/  # level should be numbers with optional .5 increments
     186*   : W : height == * && height != /^(([0-9]+\.?[0-9]*( m)?)|([1-9][0-9]*\'((10|11|[0-9])((\.[0-9]+)?)\")?))$/  # meters is default; period is separator; if units, put space then unit
     187
     188*   : W : maxheight == * && maxheight != /^(([1-9][0-9]*(\.[0-9]+)?( m)?)|([0-9]+\'([0-9]|10|11)(\.[0-9]*)?\"))$/  # meters is default; period is separator; if units, put space then unit
     189way : W : width == * && width != /^(([0-9]+\.?[0-9]*( [a-z]+)?)|([0-9]+\'[0-9]+\.?[0-9]*\"))$/  # meters is default; period is separator; if units, put space then unit
     190*   : W : maxwidth == * && maxwidth != /^(([0-9]+\.?[0-9]*( m)?)|([0-9]+\'[0-9]+\.?[0-9]*\"))$/  # meters is default; period is separator; if units, put space then unit
     191way : W : maxspeed == * && maxspeed != /^(signals|none|unposted|unknown|variable|walk|[1-9][0-9]*( [a-z]+)?|[A-Z][A-Z]:(urban|rural|living_street|motorway))$/  # unusual maxspeed format
     192way : W : voltage == * && voltage == /(.*[A-Za-z].*)|.*,.*|.*( ).*/  # voltage should be in volts with no units/delimiter/spaces
     193# some users are using frequency for other purposes (not electromagnetic) with the values 'perennial' and 'intermittent'; the vast majority are 0, 16.7, 50 and 60
     194way : W : frequency == * && frequency != /^(0|[1-9][0-9]*(\.[0-9]+)?)( (kHz|MHz|GHz|THz))?$/  # unusual frequency specification
     195way : W : gauge == * && gauge != /^([1-9][0-9]{1,3}(;[1-9][0-9]{1,3})*|broad|standard|narrow)$/  # unusual train track gauge; use mm with no separator
     196# the numbers for percentage and degrees include could probably be bracketed a bit more precisely
     197way : W : incline == * && include != /^(up|down|-?([0-9]+?(\.[1-9]%)?|100)[%°]?)$/  # unusual incline; use percentages/degrees or up/down
  • test/data/regexp-data.json

     
     1{
     2        "tests": [
     3                {
     4                        "key": "layer",
     5                        "regexp": "^0$|^-?[1-5]$",
     6                        "match": [
     7                                "0", "1", "2", "3", "4", "5", "-1", "-2", "-3", "-4", "-5"
     8                        ],
     9                        "reject": [
     10                                "+1", "+2", "+3", "+4", "+5", "zero", "yes", "no", "o", "1,2", "'-1", "1;0", "01", "!", "46", "-2000"
     11                        ]
     12                },
     13                {
     14                        "key": "level",
     15                        "regexp": "^((([0-9]|-[1-9])|[1-9][0-9]*)(\\.5)?)(;(([0-9]|-[1-9])|[1-9][0-9]*)(\\.5)?)*$|^-0\\.5$",
     16                        "match": [
     17                                "163", "88", "-1", "-2", "0", "1", "10", "0;1", "0.5", "1.5", "-0.5", "-1.5"
     18                        ],
     19                        "reject": [
     20                                "01", "+1", "0,1", "0; 1", "0 ;1", "1.33"
     21                        ]
     22                },
     23                {
     24                        "key": "height",
     25                        "regexp": "^(([0-9]+\\.?[0-9]*( m)?)|([1-9][0-9]*\\'((10|11|[0-9])((\\.[0-9]+)?)\\\")?))$",
     26                        "match": [
     27                                "4 m", "0.8", "11'4\"", "10", "2.5", "10 m", "10.2", "10'", "10'0\"", "9'5.5\""
     28                        ],
     29                        "reject": [
     30                                ">20", "10m", "10.2m"
     31                        ]
     32                },
     33                {
     34                        "key": "maxheight",
     35                        "regexp": "^(([1-9][0-9]*(\\.[0-9]+)?( m)?)|([0-9]+\\'([0-9]|10|11)(\\.[0-9]*)?\\\"))$",
     36                        "match": [
     37                                "3", "3 m", "3.8", "3.8 m", "6'7\"", "7'0\"", "2.3 m", "7'9\"", "16'3\""
     38                        ],
     39                        "reject": [
     40                                "3.8m", "3.8 meters", "0,6", "7 ft", "7'", "2.3; 7'9\"", "16' 0\""
     41                        ]
     42                },
     43                {
     44                        "key": "width",
     45                        "regexp": "^(([0-9]+\\.?[0-9]*( [a-z]+)?)|([0-9]+\\'[0-9]+\\.?[0-9]*\\\"))$",
     46                        "match": [
     47                                "2", "2 m", "0.6 mi", "16'3\"", "12.2", "2.5", "2.00", "0.30479999"
     48                        ],
     49                        "reject": [
     50                                "2m", "12' 6\"", "2km", "0,6", "2,5", "3,00", "8' - 10'", ".2"
     51                        ]
     52                },
     53                {
     54                        "key": "maxwidth",
     55                        "regexp": "^(([0-9]+\\.?[0-9]*( m)?)|([0-9]+\\'[0-9]+\\.?[0-9]*\\\"))$",
     56                        "match": [
     57                                "2", "3 m", "2.2", "6'6\"", "10'0\"", "3.6576", "2.50", "33.05"
     58                        ],
     59                        "reject": [
     60                                "3.8m", "2.8 meters", "0,6", "7 ft", "6.5 ft", "7'", "2.3; 7'9\"", "13' 6\"", "7ft6in", "2m"
     61                        ]
     62                },
     63                {
     64                        "key": "maxspeed",
     65                        "regexp": "^(signals|none|unposted|unknown|variable|walk|[1-9][0-9]*( [a-z]+)?|[A-Z][A-Z]:(urban|rural|living_street|motorway))$",
     66                        "match": [
     67                                "50", "30", "60", "30 mph", "RO:urban", "100", "none", "10 knots", "signals", "RU:rural", "5", "250", "walk"
     68                        ],
     69                        "reject": [
     70                                "70mph", "ru:urban"
     71                        ]
     72                },
     73                {
     74                        "key": "frequency",
     75                        "regexp": "^(0|[1-9][0-9]*(\\.[0-9]+)?)( (kHz|MHz|GHz|THz))?$",
     76                        "match": [
     77                                "0", "16.7", "50", "60", "16.67"
     78                        ],
     79                        "reject": [
     80                                "16.7 ; 50", "16,7", "680kHz", "50 khz", "50 KHZ"
     81                        ]
     82                },
     83                {
     84                        "key": "gauge",
     85                        "regexp": "^([1-9][0-9]{1,3}(;[1-9][0-9]{1,3})*|broad|standard|narrow)$",
     86                        "match": [
     87                                "1435", "750", "1000;1435", "broad", "standard", "narrow", "127;184", "89;127;184", "89;127;144;184"
     88                        ],
     89                        "reject": [
     90                                "1435mm"
     91                        ]
     92                },
     93                {
     94                        "key": "incline",
     95                        "regexp": "^(up|down|-?([0-9]+?(\\.[1-9]%)?|100)[%°]?)$",
     96                        "match": [
     97                                "up", "down", "10%", "-10%", "12%", "15%", "0", "5%", "10", "15", "-10°", "-6%", "10°", "5°", "-5°"
     98                        ],
     99                        "reject": [
     100                                "10 °", "5 °", "10 %", "-10 %", "5 %", "-5 %", "11.7 %", "2,5%", "3,5", "+33%", "incline=20°", "yes;10%"
     101                        ]
     102                },
     103                {
     104                        "key": "voltage",
     105                        "regexp": "(.*[A-Za-z].*)|.*,.*|.*( ).*",
     106                        "match": [
     107                                "15 kV", "15,000", "11000; 400", "11000,400", "11000 ;400"
     108                        ],
     109                        "reject": [
     110                                "15000", "25000", "3000", "1500", "750", "110000", "11000;400", "380000;220000;110000"
     111                        ],
     112                        "comment": "This test is reversed, it checks for violations rather than what is permitted. No units, no whitespace, no comma for thousands separator."
     113                }
     114        ]
     115}
     116
  • test/unit/org/openstreetmap/josm/data/validation/tests/TagCheckerTest.java

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: test/lib/gson-2.2.4.jar
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.validation.tests;
     3
     4import java.io.FileNotFoundException;
     5import java.io.FileReader;
     6import java.util.ArrayList;
     7import java.util.List;
     8import java.util.regex.Matcher;
     9import java.util.regex.Pattern;
     10
     11import org.junit.Assert;
     12import org.junit.Assume;
     13import org.junit.Before;
     14import org.junit.Test;
     15import org.openstreetmap.josm.Main;
     16import org.openstreetmap.josm.data.Preferences;
     17
     18import com.google.gson.Gson;
     19
     20public class TagCheckerTest {
     21
     22    private TagChecker tc;
     23    private Gson gson;
     24    private RegexpTests testSet;
     25
     26    private class RegexpTestInstance {
     27        public String key;
     28        public List<String> match;
     29        public List<String> reject;
     30        public String regexp;
     31    }
     32
     33    public class RegexpTests {
     34        public List<RegexpTestInstance> tests = new ArrayList<RegexpTestInstance>();
     35    }
     36
     37    @Before
     38    public void setUp() throws Exception {
     39        Main.pref = new Preferences();
     40        tc = new TagChecker();
     41        tc.initialize();
     42        gson = new Gson();
     43    }
     44
     45    @Test
     46    public void testRegularExpressions() {
     47        Assume.assumeTrue(TagChecker.checkerData.size() > 0);
     48        FileReader jsonFileReader = null;
     49
     50        try {
     51            jsonFileReader = new FileReader("test/data/regexp-data.json");
     52            testSet = gson.fromJson(jsonFileReader, RegexpTests.class);
     53        } catch (FileNotFoundException e) {
     54            Assert.fail(e.getMessage());
     55        } finally {
     56            if (jsonFileReader != null) {
     57                try { jsonFileReader.close(); } catch (Throwable t) {}
     58            }
     59        }
     60
     61        for (TagChecker.CheckerData cd : TagChecker.checkerData) {
     62            for (TagChecker.CheckerData.CheckerElement ce : cd.data) {
     63                RegexpTestInstance testInstance = null;
     64                if (ce.value instanceof Pattern) {
     65                    validateCheckerAgainstRegexpData(ce, testInstance);
     66                }
     67            }
     68        }
     69    }
     70
     71    private void validateCheckerAgainstRegexpData(TagChecker.CheckerData.CheckerElement ce,
     72            RegexpTestInstance testInstance) {
     73        Pattern patternFromCfg = (Pattern)ce.value;
     74        for (RegexpTestInstance rti : testSet.tests) {
     75            if (rti.regexp.compareTo( patternFromCfg.pattern()) == 0) {
     76                testInstance = rti;
     77                System.out.println(rti.key);
     78                break;
     79            }
     80        }
     81        if (testInstance == null) {
     82            System.out.println("No tests found for regexp='" + patternFromCfg + "'");
     83        } else {
     84            // Run through the checks
     85            for (String acceptString : testInstance.match) {
     86                Matcher matcher = patternFromCfg.matcher(acceptString);
     87                Assert.assertTrue(testInstance.key + ": " + acceptString + " should match", matcher.matches());
     88            }
     89            for (String rejectString : testInstance.reject) {
     90                Matcher matcher = patternFromCfg.matcher(rejectString);
     91                Assert.assertFalse(testInstance.key + ": " + rejectString + " should not match", matcher.matches());
     92            }
     93        }
     94    }
     95}