Warning, file /libraries/kopeninghours/autotests/parsertest.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include <KOpeningHours/OpeningHours> 0008 0009 #include <QTest> 0010 0011 using namespace KOpeningHours; 0012 0013 class ParserTest : public QObject 0014 { 0015 Q_OBJECT 0016 private Q_SLOTS: 0017 void testSuccess_data() 0018 { 0019 QTest::addColumn<QByteArray>("input"); 0020 QTest::addColumn<QByteArray>("expectedOutput"); 0021 QTest::addColumn<QByteArray>("expectedSimplifiedOutput"); 0022 0023 #define T(x) QTest::newRow(x) << QByteArray(x) << QByteArray(x) << QByteArray(x) 0024 #define T2(x, y) QTest::newRow(x) << QByteArray(x) << QByteArray(y) << QByteArray(y) 0025 #define T3(x, y, z) QTest::newRow(x) << QByteArray(x) << QByteArray(y ? y : x) << QByteArray(z) 0026 T("24/7"); 0027 T("24/7 \"comment\""); 0028 T("24/7 closed"); 0029 T("24/7 unknown \"comment\""); 0030 T("unknown \"comment\""); 0031 T("off"); 0032 T("Dec off"); 0033 T("Dec 25 off"); 0034 T("Dec 25-26 off"); 0035 T("Dec 24-26,31 off"); 0036 T2("Jan 1,6 off", "Jan 01,06 off"); 0037 T("Dec 24,25,26"); 0038 T2("Jan 03,Dec 04,24 off", "Jan 03,Dec 04,24 off"); 0039 T2("Jan 03, Dec 04, 24 off", "Jan 03,Dec 04,24 off"); 0040 T2("07:30-20:00; Jan 03,13,23,Dec 04,14,24 off", "07:30-20:00; Jan 03,13,23,Dec 04,14,24 off"); 0041 T("Dec 08:00"); 0042 T("Dec 08:00-14:00"); 0043 T("easter off"); 0044 T("easter +1 day off"); 0045 T("easter -2 days off"); 0046 T2("whitsun off", "easter +49 days off"); 0047 T2("whitsun +1 day off", "easter +50 days off"); 0048 T("2020"); 0049 T("2020-2021"); 0050 T("1970-2022/2"); 0051 T("2020+"); 0052 T("2010,2020,2030"); 0053 T("2010-2015,2020-2025,2030"); 0054 T("2020-2022 Dec"); 0055 T("2020 Dec-2022 Dec"); 0056 T("2020-2022 Dec 24-26"); 0057 T("2020 Dec 24-26"); 0058 T("2021 10:00-20:00"); 0059 T("PH off || open"); // https://openingh.openstreetmap.de/evaluation_tool/ says this means always open... bug in opening.js? 0060 T("PH off || unknown \"foo\""); 0061 T("2020 Jan-Apr"); 0062 T("1980-2030/4"); 0063 T("\"comment\""); 0064 T("PH off || 2020 open"); 0065 T("Mo[1-2,4]"); 0066 T2("We[-1] + 2 days", "We[-1] +2 days"); 0067 T("10:00-16:00/15"); 0068 T2("10:00-16:00/90", "10:00-16:00/01:30"); 0069 T2("10:00-16:00/1:30", "10:00-16:00/01:30"); 0070 T("10:00-10:00"); 0071 T("PH off || open || unknown"); 0072 T("10:00-12:00+"); 0073 T("Jun 15-Aug 15 Mo-Fr 10:00-12:30"); 0074 T2("Dec 01 +Su", "Dec 01 Su[1]"); 0075 T2("Dec 01 -Su 08:00-12:00", "Dec 01 Su[-1] 08:00-12:00"); 0076 T("Aug Mo[1]-Aug Sa[-1] closed"); 0077 T("2020/2"); 0078 T("\"Außerhalb der Semesterferien\": Mo-Fr 08:00-22:00; Sa,Su 10:00-20:00; \"Innerhalb der Semesterferien\": Mo-Fr 08:00-18:00; Sa,Su 10:00-16:00"); 0079 T("PH Mo-Th 14:00-23:00"); 0080 T2("Mo-Th PH 14:00-23:00", "PH Mo-Th 14:00-23:00"); 0081 T("PH Fr,SH Fr 11:30-02:00"); 0082 T2("PH Fr, SH Fr 11:30-02:00", "PH Fr,SH Fr 11:30-02:00"); 0083 T2("PH Th,Fr, SH Tu,Fr 11:30-02:00", "PH Th,Fr,SH Tu,Fr 11:30-02:00"); 0084 T3("Mo-Th 17:00-23:00, Mo-Th SH 14:00-23:00, Fr 14:00-02:00, Sa 11:30-22:00, Su 11:30-22:00, PH Mo-Th 11:30-23:00, PH Fr, SH Fr 11:30-02:00, PH Sa-Su 11:30-22:00", 0085 "Mo-Th 17:00-23:00, SH Mo-Th 14:00-23:00, Fr 14:00-02:00, Sa 11:30-22:00, Su 11:30-22:00, PH Mo-Th 11:30-23:00, PH Fr,SH Fr 11:30-02:00, PH Sa-Su 11:30-22:00", 0086 "Mo-Th 17:00-23:00, SH Mo-Th 14:00-23:00, Fr 14:00-02:00, Sa,Su 11:30-22:00, PH Mo-Th 11:30-23:00, PH Fr,SH Fr 11:30-02:00, PH Sa-Su 11:30-22:00"); 0087 T("Sa,Su,PH,Mo"); 0088 T2("Tu-Fr 10:00-17:00; Th 10:00-20:00; Sa,Su,PH Mo 11:00-18:00", "Tu-Fr 10:00-17:00; Th 10:00-20:00; Sa,Su,PH,Mo 11:00-18:00"); 0089 T2("Mo,We,Th PH off", "PH Mo,We,Th off"); 0090 T2("PH closed \"\"", "PH closed"); 0091 T("Mar 01-Mar Su[-1] 17:00-18:00; PH off"); 0092 T("Mar 01-Mar Su[-2] Mo 17:00-18:00; PH off"); 0093 T("Oct Su[-1]-Dec 31 08:00-18:00"); 0094 T("Oct Su[-1]-Dec 31 Su 08:00-18:00"); 0095 T("Mar Su[1]-Oct Su[1]: 11:00-20:00; PH 11:00-20:00"); 0096 T2("Mo 20:00-26:00", "Mo 20:00-26:00"); // https://github.com/osm-fr/osmose-backend/issues/1344 0097 0098 // https://bugs.kde.org/show_bug.cgi?id=445963 0099 T("Th[1-2] 09:30-11:45"); 0100 T("Th[1,2] 09:30-11:45"); 0101 T("Mo[1,3,-1]"); // order as desired, -1 means last 0102 T("Mo[1,3,2]"); // currently not normalized 0103 0104 // from https://wiki.openstreetmap.org/wiki/Key:opening_hours#Simple_examples 0105 T("Mo-Fr 08:00-17:30"); 0106 T("Mo-Fr 08:00-12:00,13:00-17:30"); 0107 T("Mo-Fr 08:00-12:00,13:00-17:30; Sa 08:00-12:00"); 0108 T("Mo-Fr 08:00-12:00,13:00-17:30; Sa 08:00-12:00; PH off"); 0109 T("Mo-Fr 08:00-12:00,13:00-17:30; Sa 08:00-12:00; PH 09:00-12:00"); 0110 0111 // from https://wiki.openstreetmap.org/wiki/Key:opening_hours#Examples 0112 T3("Sa-Su 00:00-24:00", nullptr, "Sa,Su 00:00-24:00"); 0113 T("Mo-Fr 08:30-20:00"); 0114 T("Mo 10:00-12:00,12:30-15:00; Tu-Fr 08:00-12:00,12:30-15:00; Sa 08:00-12:00"); 0115 T("Mo-Su 08:00-18:00; Apr 10-15 off; Jun 08:00-14:00; Aug off; Dec 25 off"); 0116 T("Mo-Sa 10:00-20:00; Tu off"); 0117 T("Mo-Sa 10:00-20:00; Tu 10:00-14:00"); 0118 T("sunrise-sunset"); 0119 T("Su 10:00+"); 0120 T2("week 1-53/2 Fr 09:00-12:00; week 2-52/2 We 09:00-12:00", "week 01-53/2 Fr 09:00-12:00; week 02-52/2 We 09:00-12:00"); 0121 T("Mo-Sa 08:00-13:00,14:00-17:00 || \"by appointment\""); 0122 T3("Su-Tu 11:00-01:00, We-Th 11:00-03:00, Fr 11:00-06:00, Sa 11:00-07:00", nullptr, "Su-Tu 11:00-01:00, We,Th 11:00-03:00, Fr 11:00-06:00, Sa 11:00-07:00"); 0123 T("Mo-Su,PH 15:00-03:00; easter -2 days off"); 0124 0125 // from https://openingh.openstreetmap.de/evaluation_tool/ 0126 T("Mo-Fr 10:00-20:00; PH off"); 0127 T("Mo,Tu,Th,Fr 12:00-18:00; Sa,PH 12:00-17:00; Th[3],Th[-1] off"); 0128 T("00:00-24:00; Tu-Su,PH 08:30-09:00 off; Tu-Su 14:00-14:30 off; Mo 08:00-13:00 off"); 0129 T3("Fr-Sa 18:00-06:00; PH off", nullptr, "Fr,Sa 18:00-06:00; PH off"); 0130 T("Mo 10:00-12:00,12:30-15:00"); 0131 T("Mo 10:00-12:00,12:30-15:00; Tu-Fr 08:00-12:00,12:30-15:00; Sa 08:00-12:00"); 0132 T("\"only after registration\"; PH off"); 0133 T("22:00-23:00; PH off"); 0134 T("08:00-11:00; PH off"); 0135 T("open; Mo 15:00-16:00 off; PH off"); 0136 T("Mo-Su 22:00-23:00; We,PH off"); 0137 T("We-Fr 10:00-24:00 open \"it is open\" || \"please call\"; PH off"); 0138 T("Mo-Fr 08:00-11:00 || Tu-Th,PH open \"Emergency only\""); 0139 T3("Tu-Th,We 22:00-23:00 open \"Hot meals\"; PH off", nullptr, "Tu-Th 22:00-23:00 open \"Hot meals\"; PH off"); // We redundant 0140 T("Mo 12:00-14:00 open \"female only\", Mo 14:00-16:00 open \"male only\"; PH off"); 0141 T("Apr: 22:00-23:00; PH off"); 0142 T("Jul-Jan: 22:00-23:00; PH off"); 0143 T("Jan-Jul: 22:00-23:00; PH off"); 0144 T2("Jul 23-Jan 3: \"needs reservation by phone\"; PH off", "Jul 23-Jan 03: \"needs reservation by phone\"; PH off"); 0145 T2("Jul 23-Jan 3: 22:00-23:00 \"Please make a reservation by phone.\"; PH off", "Jul 23-Jan 03: 22:00-23:00 \"Please make a reservation by phone.\"; PH off"); 0146 T2("Jul 23-Jan 3: 08:00-11:00 \"Please make a reservation by phone.\"; PH off", "Jul 23-Jan 03: 08:00-11:00 \"Please make a reservation by phone.\"; PH off"); 0147 T2("Jan 23-Jul 3: 22:00-23:00 \"Please make a reservation by phone.\"; PH off", "Jan 23-Jul 03: 22:00-23:00 \"Please make a reservation by phone.\"; PH off"); 0148 T("Mar Su[-1]-Dec Su[1] -2 days: 22:00-23:00; PH off"); 0149 T("Sa[1],Sa[1] +1 day 10:00-12:00 open \"first weekend in the month\"; PH off"); 0150 T("Sa[-1],Sa[-1] +1 day 10:00-12:00 open \"last weekend in the month\"; PH off"); 0151 T3("Sa-Su 00:00-24:00; PH off", nullptr, "Sa,Su 00:00-24:00; PH off"); 0152 T("Mo-Fr 00:00-24:00; PH off"); 0153 T("sunrise-sunset open \"Beware of sunburn!\"; PH off"); 0154 T("sunset-sunrise open \"Beware of vampires!\"; PH off"); 0155 T("(sunrise-00:30)-(sunrise+00:30)"); 0156 T("(sunset+01:00)-24:00 || closed \"No drink before sunset!\"; PH off"); 0157 T("22:00+; PH off"); 0158 T("Tu,PH 23:59-22:59"); 0159 T("We-Mo,PH 23:59-22:59"); 0160 T2("week 2-52/2 We 00:00-24:00; week 1-53/2 Sa 00:00-24:00; PH off", "week 02-52/2 We 00:00-24:00; week 01-53/2 Sa 00:00-24:00; PH off"); 0161 T2("week 4-16 We 00:00-24:00; week 38-42 Sa 00:00-24:00; PH off", "week 04-16 We 00:00-24:00; week 38-42 Sa 00:00-24:00; PH off"); 0162 T("2012 easter -2 days-2012 easter +2 days: open \"Around easter\"; PH off"); 0163 T("24/7 closed \"always closed\""); 0164 T2("2013,2015,2050-2053,2055/2,2020-2029/3,2060+ Jan 1", "2013,2015,2050-2053,2055/2,2020-2029/3,2060+ Jan 01"); 0165 T2("Jan 23-Feb 11,Feb 12 00:00-24:00; PH off", "Jan 23-Feb 11,Feb 12 00:00-24:00; PH off"); 0166 T("Apr-Oct Su[2] 14:00-18:00; Aug Su[-1] -1 day 10:00-18:00; Aug Su[-1] 10:00-18:00; PH off"); 0167 T("Mo-Fr 08:00-12:00, We 14:00-18:00; Su,PH off"); // open We morning too 0168 T("Mo-Fr 08:00-12:00; We 14:00-18:00; Su,PH off"); // closed We morning 0169 T2("April-September; Mo-Fr 09:00-13:00, 14:00-18:00, Sa 10:00-13:00", "Apr-Sep; Mo-Fr 09:00-13:00,14:00-18:00, Sa 10:00-13:00"); 0170 0171 T("We; PH off"); 0172 T("PH"); 0173 T("PH Mo-Fr"); 0174 T("PH -1 day"); 0175 T("SH"); 0176 T("SH,PH"); 0177 T("PH,SH"); 0178 T("We[1-3]"); 0179 T("We[3-5]"); 0180 T("Sa"); 0181 T("Sa[1]"); 0182 T("Sa[1-3]"); 0183 T("Su[-1,1]"); 0184 T("Tu-Th"); 0185 T("Fr-Mo"); 0186 T("Mo-Su; We \"only after registration\""); 0187 T("Oct: We[1]"); 0188 0189 // from https://github.com/dfaure/DataNovaImportScripts/blob/master/saved_opening_hours 0190 T3("Mo-Tu,Th-Fr 09:30-12:00; 2020 Dec 28 off; 2020 Dec 22,2020 Dec 29 off; We 15:00-17:00; 2020 Dec 23,2020 Dec 30 off; 2020 Dec 24,2020 Dec 31 off; Sa 10:00-12:00; 2020 Dec 26,2021 Jan 02 off; PH off", 0191 "Mo-Tu,Th-Fr 09:30-12:00; 2020 Dec 28 off; 2020 Dec 22,29 off; We 15:00-17:00; 2020 Dec 23,30 off; 2020 Dec 24,31 off; Sa 10:00-12:00; 2020 Dec 26,2021 Jan 02 off; PH off", 0192 "Mo,Tu,Th,Fr 09:30-12:00; 2020 Dec 28 off; 2020 Dec 22,29 off; We 15:00-17:00; 2020 Dec 23,30 off; 2020 Dec 24,31 off; Sa 10:00-12:00; 2020 Dec 26,2021 Jan 02 off; PH off"); 0193 0194 // real-world tests from Osmose that we were handling wrongly 0195 T("Tu-Fr 11:30-14:30 open, 14:30-18:00 open \"pickup only\", 18:00-22:00 open"); 0196 T("SH Tu,Th 10:00-19:00"); 0197 T2("Apr-Sep 09:00-19:00; Mar-Oct. 09:00-18:00; Nov.-Feb. 09:00-17:00", "Apr-Sep 09:00-19:00; Mar-Oct 09:00-18:00; Nov-Feb 09:00-17:00"); 0198 T2("week 23-37 12:30-15:00,20:00-23:00; week 01-22,38-53 off", "week 23-37 12:30-15:00,20:00-23:00; week 01-22,38-53 off"); 0199 T("Mo-Sa 09:00-20:00; Su[-2,-1] 12:30-18:00"); 0200 T("Su off, Mo-Fr 08:30-13:00; Mo-Th 08:30-13:30,16:00-20:00"); 0201 T3("Mo-Tu 09:00-12:00,14:00-18:00, We closed, Th-Sa 09:00-12:00,14:00-18:00; Su 09:30-12:30,14:30-18:00", nullptr, 0202 "Mo,Tu 09:00-12:00,14:00-18:00, We closed, Th-Sa 09:00-12:00,14:00-18:00; Su 09:30-12:30,14:30-18:00"); 0203 T2("SH Sep-Jun Mo 10:52-15:52", "SH, Sep-Jun Mo 10:52-15:52"); // likely incorrect, but at least no information loss 0204 0205 // weekday autocorrect 0206 T2("Tu, Th 13:30-19:00; SH Tu, Th 10:00-19:00; Fr 13:30-18:00; SH Fr 10:00-18:00; We, Sa 10:00-18:00; SH We, Sa 10:00-18:00", "Tu,Th 13:30-19:00; SH Tu,Th 10:00-19:00; Fr 13:30-18:00; SH Fr 10:00-18:00; We,Sa 10:00-18:00; SH We,Sa 10:00-18:00"); 0207 T2("Mar Su[-1] - Oct Su[-1] - 1 days: Th 09:00-18:00, Tu 15:00-18:00; Sa 09:00-12:00; Oct Su[-1] - Mar Su[-1] - 1 days: Tu 09:00-17:00, Th 09:00-17:00, Sa 09:00-12:00; Mo, We, Fr, Su, PH Off", 0208 "Mar Su[-1]-Oct Su[-1] -1 day: Th 09:00-18:00, Tu 15:00-18:00; Sa 09:00-12:00; Oct Su[-1]-Mar Su[-1] -1 day: Tu 09:00-17:00, Th 09:00-17:00, Sa 09:00-12:00; Mo,We,Fr,Su,PH off"); 0209 T2("Sep 16-Jun 15: Tu-Fr, Sa, Su [1,3] 09:00-14:00; Jun 16-Sep 15: Sa, Su [1,3] 13:00-19:00; Mo off, Su [2,4] off", 0210 "Sep 16-Jun 15: Tu-Fr,Sa,Su[1,3] 09:00-14:00; Jun 16-Sep 15: Sa,Su[1,3] 13:00-19:00; Mo off, Su[2,4] off"); 0211 T2("2020-2021 Mo, Tu-Fr, Sa [-1] 09:00-14:00", "2020-2021 Mo,Tu-Fr,Sa[-1] 09:00-14:00"); 0212 T2("week 1-3 Mo[2], Tu-Fr, Sa [-1] 09:00-14:00", "week 01-03 Mo[2],Tu-Fr,Sa[-1] 09:00-14:00"); 0213 T2("Mo Fr 09:30-12:30 13:30-18:30", "Mo,Fr 09:30-12:30,13:30-18:30"); 0214 T2("Mo Fr 09:30-12:30, 13:30-18:30 off", "Mo,Fr 09:30-12:30,13:30-18:30 off"); 0215 T2("Mo, We, Fr 06:30-21:30; Tu, Th 09:00-21:30; Sa 09:00-17:00; Su 09:00-14:00", "Mo,We,Fr 06:30-21:30; Tu,Th 09:00-21:30; Sa 09:00-17:00; Su 09:00-14:00"); 0216 T2("Lunes a sábado, 9:30 AM-5:30 PM", "Mo-Sa 09:30-17:30"); // bug 445784 0217 0218 // lists of specific days 0219 T("2021 Dec 26-28,30-31,2022 Jan 02-03 off"); 0220 T2("2021 Dec 26-28,Dec 30-31,2022 Jan 02-03 off", "2021 Dec 26-28,30-31,2022 Jan 02-03 off"); 0221 T2("2021 Dec 22, 26-28, 29, 31, 2022 Jan 02-03 off", "2021 Dec 22,26-28,29,31,2022 Jan 02-03 off"); 0222 0223 // technically wrong but often found content in OSM for which we have error recovery 0224 T2("So", "Su"); 0225 T2("Ph", "PH"); 0226 T2("9:00-12:00", "09:00-12:00"); 0227 T2("Mo-Fr 09:00-18:30;Sa 09:00-17:00", "Mo-Fr 09:00-18:30; Sa 09:00-17:00"); 0228 T2("08:00-12:00;", "08:00-12:00"); 0229 T2("14:00-20:00,", "14:00-20:00"); 0230 T2("Mo 14:00-21:00; Tu-Th 10:00-21:00; Fr 10:00-18:00;Su, PH off|| \"Samstag zweimal im Monat, Details siehe Webseite\"", "Mo 14:00-21:00; Tu-Th 10:00-21:00; Fr 10:00-18:00; Su,PH off || \"Samstag zweimal im Monat, Details siehe Webseite\""); 0231 T2("Mo-Fr 06:30-12:00, 13:00-18:00", "Mo-Fr 06:30-12:00,13:00-18:00"); // see autocorrect() 0232 T2("we-mo 11:30-14:00, 17:30-22:00; tu off", "We-Mo 11:30-14:00,17:30-22:00; Tu off"); 0233 T2("01:00-23:00; ", "01:00-23:00"); 0234 T2("02:00-22:00,\n", "02:00-22:00"); 0235 T2("Friday 08:00-12:00", "Fr 08:00-12:00"); 0236 T2("Sat", "Sa"); 0237 T2("december", "Dec"); 0238 T2("Dec 24,25,26, Jan 1,6 off", "Dec 24,25,26,Jan 01,06 off"); 0239 T2("Dec 24,25,26 open, Jan 1,6 off", "Dec 24,25,26 open, Jan 01,06 off"); 0240 T2("Dec 6,4", "Dec 06,04"); 0241 T2("Dec 3,2,1", "Dec 03,02,01"); 0242 T2("07:30-20:00; Jan 03, 13, 23, Feb 03, 13, 23, Mar 03, 13, 23, Apr 03, 13, 23, Jun 03, 13, 23, Jul 03, 13, 23, Aug 03, 13, 23, Sep 03, 13, 23, Oct 03, 13, 23, Nov 03, 13, 23, Dec 03, 13, 23 off", 0243 "07:30-20:00; Jan 03,13,23,Feb 03,13,23,Mar 03,13,23,Apr 03,13,23,Jun 03,13,23,Jul 03,13,23,Aug 03,13,23,Sep 03,13,23,Oct 03,13,23,Nov 03,13,23,Dec 03,13,23 off"); 0244 T2("Apr, May, Oct, Nov, Dec: Mo-Su, 10:00-19:00; Jun-Sep: Mo-Su:10:00-20:00", "Apr,May,Oct,Nov,Dec: Mo-Su, 10:00-19:00; Jun-Sep: Mo-Su 10:00-20:00"); 0245 0246 // Tolerance for incorrect casing 0247 T2("mo-fr 10:00-20:00", "Mo-Fr 10:00-20:00"); 0248 T2("jan-feb 10:00-20:00", "Jan-Feb 10:00-20:00"); 0249 T2("jan-feb,aug 10:00-20:00", "Jan-Feb,Aug 10:00-20:00"); 0250 T2("SUNRISE-SUNSET", "sunrise-sunset"); 0251 T2("(SUNrISE-01:00)-(SUnsET+01:00)", "(sunrise-01:00)-(sunset+01:00)"); 0252 T2("su,sh off", "Su,SH off"); 0253 T2("mo-fr CLOSED", "Mo-Fr closed"); 0254 0255 // Time correction 0256 T2("9h00-12h00", "09:00-12:00"); 0257 T2("9h-12h", "09:00-12:00"); 0258 T2("5H", "05:00"); 0259 T2("06:00am", "06:00"); 0260 T2("06:30pm", "18:30"); 0261 T2("07:00 am", "07:00"); 0262 T2("07:00 pm", "19:00"); 0263 T2("5:00AM", "05:00"); 0264 T2("5:02 PM", "17:02"); 0265 T2("10a", "10:00"); 0266 T2("10p", "22:00"); 0267 T2("12:00 am", "00:00"); 0268 T2("12:00pm", "12:00"); 0269 T2("1 a.m", "01:00"); 0270 T2("3p.m", "15:00"); 0271 T2("12:01a.m.", "00:01"); 0272 T2("12:01p.m.", "12:01"); 0273 T2("11:59a", "11:59"); 0274 T2("11:59p", "23:59"); 0275 T2("9h00-12h00,14:00-17:00", "09:00-12:00,14:00-17:00"); 0276 T2("9:00 am - 12:00 am", "09:00-24:00"); 0277 T2("9 am - 12 am", "09:00-24:00"); 0278 T2("11:00 am - 11:00 pm", "11:00-23:00"); 0279 T2("09 : 00 - 12 : 00 , 13 : 00 - 19 : 00", "09:00-12:00,13:00-19:00"); 0280 T2("10.30am - 4.30pm", "10:30-16:30"); 0281 T2("17時00分~23時30分", "17:00-23:30"); 0282 0283 // alternative range separators 0284 T2("Mo-Fri 10am to 7pm, Saturday 11am to 6pm, Sun 11am to 4pm", "Mo-Fr 10:00-19:00, Sa 11:00-18:00, Su 11:00-16:00"); 0285 T2("Monday to Friday 8:00AM to 4:30PM", "Mo-Fr 08:00-16:30"); 0286 T2("1pm-3pm and 7pm-11pm", "13:00-15:00,19:00-23:00"); 0287 T2("8h00 à 12h00 et 13h30 à 18h00", "08:00-12:00,13:30-18:00"); 0288 T2("Samedi et Dimanche 5h30 - 12h30 Lundi 13h45 - 15h15", "Sa,Su 05:30-12:30; Mo 13:45-15:15"); 0289 T2("Mo-Th 11:00-20:00 Friday & Saturday 11:00-21:00 Sunday 12:00-19:00", "Mo-Th 11:00-20:00; Fr,Sa 11:00-21:00; Su 12:00-19:00"); 0290 T2("11:30-14:00、16:30-22:00", "11:30-14:00,16:30-22:00"); 0291 T2("Lunedì al Venerdì 08:00-13:00", "Mo-Fr 08:00-13:00"); 0292 T2("Monday through Friday 09:00 - 17:00", "Mo-Fr 09:00-17:00"); 0293 0294 // (mis)use of colon as a small-range selector separator 0295 T2("Fr: 17:00-19:00", "Fr 17:00-19:00"); 0296 T2("Fr: closed", "Fr closed"); 0297 T2("Tu-Su:07:00-00:00", "Tu-Su 07:00-24:00"); 0298 T2("Du lundi au vendredi : 9:00-18:00", "Mo-Fr 09:00-18:00"); 0299 0300 // Unicode symbols 0301 T3("Mo–Tu", "Mo-Tu", "Mo,Tu"); 0302 T2("13:41", "13:41"); 0303 T2("10:00〜19:00", "10:00-19:00"); 0304 T2("10:00-17:00", "10:00-17:00"); 0305 T2("11:00−23:00", "11:00-23:00"); 0306 T2("11:00ー15:00", "11:00-15:00"); 0307 T2("We 09:00-18:00\xC2\xA0; Sa 09:00-19:00", "We 09:00-18:00; Sa 09:00-19:00"); // weird space 0308 T2("LUNDI 08:30 – 17:00", "Mo 08:30-17:00"); 0309 T3("月,木,金,土,日 11:00-19:00", "Mo,Th,Fr,Sa,Su 11:00-19:00", "Th-Mo 11:00-19:00"); 0310 T2("月-土 09:00-18:00", "Mo-Sa 09:00-18:00"); 0311 T2("水曜日~土曜日10:00~19:00", "We-Sa 10:00-19:00"); 0312 T2("月~土 17:00~23:00", "Mo-Sa 17:00-23:00"); 0313 T2("Mo-Fr 08:00-17:00 “Visa Applications\"", "Mo-Fr 08:00-17:00 \"Visa Applications\""); 0314 T2("„nach Vereinbarung“", "\"nach Vereinbarung\""); 0315 T("\"„Termine nach Vereinbarung“\""); 0316 0317 // non-English 0318 T2("Lundi au Vendredi 8h - 17h en continu", "Mo-Fr 08:00-17:00"); 0319 T2("Lun-Ven 08:00-13:00", "Mo-Fr 08:00-13:00"); 0320 T2("Lu-Sa 08:00-13:00", "Mo-Sa 08:00-13:00"); 0321 T2("Domingo de 9: 00 am. a 1:00 pm", "Su 09:00-13:00"); 0322 T2("Gio, Sab e Dom: 9.00-12.30", "Th,Sa,Su 09:00-12:30"); 0323 T2("Segunda a Sexta 08:00h a 16:00h", "Mo-Fr 08:00-16:00"); 0324 T2("lunedi,mercoledi,venerdi,sabato 09:00-20:00", "Mo,We,Fr,Sa 09:00-20:00"); 0325 T2("Mi 08:00-18:00", "We 08:00-18:00"); 0326 T2("Du Mardi au Vendredi 11h00-13h30 Le samedi 10h-19h", "Tu-Fr 11:00-13:30; Sa 10:00-19:00"); 0327 T2("Senin-Sabtu 09:00-16:00, Minggu 09:00-18:00", "Mo-Sa 09:00-16:00, Su 09:00-18:00"); 0328 T2("Lundi-samedi 8H00-12H00 16H00-20H00 dimanche,jours fériés 9H00-12H00 17H00-20H00", "Mo-Sa 08:00-12:00,16:00-20:00; Su,PH 09:00-12:00,17:00-20:00"); 0329 T2("De février à novembre", "Feb-Nov"); 0330 T3("Me,Je,Ve 8h-12h30, 14h-19h; Sa 8h-12h30, 14h-18h", "We,Th,Fr 08:00-12:30,14:00-19:00; Sa 08:00-12:30,14:00-18:00", "We-Fr 08:00-12:30,14:00-19:00; Sa 08:00-12:30,14:00-18:00"); 0331 T2("Mo-Fr: 10:00-18:30 Uhr Sa: 10:00-13:30 Uhr", "Mo-Fr 10:00-18:30; Sa 10:00-13:30"); 0332 T2("Montag & Dienstag Ruhetag", "Mo,Tu closed"); 0333 T2("Понедельник - Суббота 09:00 - 21:00", "Mo-Sa 09:00-21:00"); 0334 T2("Пон-Пт 08:00-20:00, Суб 08:00-19:00", "Mo-Fr 08:00-20:00, Sa 08:00-19:00"); 0335 T2("Ноябрь-Март", "Nov-Mar"); 0336 T2("с 08:30 до 23:00", "08:30-23:00"); 0337 T2("рассвет - сумерки", "dawn-dusk"); 0338 T2("от рассвета до сумерек", "dawn-dusk"); 0339 T2("восход - закат", "sunrise-sunset"); 0340 T2("с восхода пo закат", "sunrise-sunset"); 0341 T2("от восхода дo заката", "sunrise-sunset"); 0342 T2("Среда открыто; Пятница закрыто; Суббота неизвестно", "We open; Fr closed; Sa unknown"); 0343 T2("Вт Выходной", "Tu closed"); 0344 T2("Mo Cerrado; Tu Abierto, Fr libre", "Mo closed; Tu open, Fr closed"); 0345 0346 // recovery from wrong rule separators 0347 T2("Fr,Sa 10:00-02:00,Su 10:00-20:00", "Fr,Sa 10:00-02:00, Su 10:00-20:00"); 0348 T2("tu-sa 12:00-14:30,mo-sa 18:30-22:00", "Tu-Sa 12:00-14:30, Mo-Sa 18:30-22:00"); 0349 T2("Mo 07:00-12:00,Tu 15:00-20:00,We 07:00-12:00,Fr 15:00-20:00", "Mo 07:00-12:00, Tu 15:00-20:00, We 07:00-12:00, Fr 15:00-20:00"); 0350 T2("Mo-Fr 09:00-17:00 Sa 09:00-14:00", "Mo-Fr 09:00-17:00; Sa 09:00-14:00"); 0351 T2("Friday 11AM–2:30AM Saturday 10AM–3:30AM Sunday 9AM–4:30AM", "Fr 11:00-02:30; Sa 10:00-03:30; Su 09:00-04:30"); 0352 T2("Mo-Sa 12:00-15:00; 18:00-24:00", "Mo-Sa 12:00-15:00,18:00-24:00"); 0353 T2("Mo-Sa 12:00-15:00; Mo-Sa 18:00-24:00", "Mo-Sa 12:00-15:00,18:00-24:00"); 0354 T2("Mo 12:00-15:00; Mo 18:00-24:00", "Mo 12:00-15:00,18:00-24:00"); 0355 T("Mo-Sa 12:00-15:00 off; 18:00-24:00"); 0356 T("Mo-Sa 12:00-15:00; Mo-Sa 18:00-24:00 closed"); 0357 T("Mo 12:00-15:00; Mo 18:00-24:00 \"comment\""); 0358 T("Sa 08:00-12:00; 11:30-13:00 off"); 0359 0360 // recovery from wrong time selector separators 0361 T3("Dimanche Fermé Lundi 08:00 – 12:30 14:00 – 19:00 Mardi 08:00 – 12:30 14:00 – 19:00 Mercredi 08:00 – 12:30 14:00 – 19:00 Jeudi 08:00 – 12:30 14:00 – 19:00 Vendredi 08:00 – 12:30 14:00 – 19:00 Samedi 08:00 – 12:30 14:30 – 18:00", 0362 "Su closed; Mo 08:00-12:30,14:00-19:00; Tu 08:00-12:30,14:00-19:00; We 08:00-12:30,14:00-19:00; Th 08:00-12:30,14:00-19:00; Fr 08:00-12:30,14:00-19:00; Sa 08:00-12:30,14:30-18:00", 0363 "Su closed; Mo-Fr 08:00-12:30,14:00-19:00; Sa 08:00-12:30,14:30-18:00"); 0364 0365 // recovery from slashes abused as rule or timespan separators 0366 T2("09:00-12:00/13:00-19:00", "09:00-12:00,13:00-19:00"); 0367 T2("10:00 - 13:30 / 17:00 - 20:30", "10:00-13:30,17:00-20:30"); 0368 T2("Mo-Fr 6:00-18:00 / Sa 6:00-13:00 / So 7:00-17:00", "Mo-Fr 06:00-18:00; Sa 06:00-13:00; Su 07:00-17:00"); 0369 0370 // Simplification of the output 0371 T3("Mo 08:00-13:00; Tu 08:00-13:00", nullptr, "Mo,Tu 08:00-13:00"); 0372 T3("Mo-Th 08:00-13:00; Sa[1],Su[-1] 08:00-13:00", "Mo-Th 08:00-13:00; Sa[1],Su[-1] 08:00-13:00", "Mo-Th,Sa[1],Su[-1] 08:00-13:00"); 0373 T("easter +1 day 08:00-13:00; Tu,Sa,Su 08:00-13:00"); // does not simplify 0374 T3("Mo-Sa 12:00-15:00, Mo-Sa 18:00-24:00", "Mo-Sa 12:00-15:00, Mo-Sa 18:00-24:00", "Mo-Sa 12:00-15:00,18:00-24:00"); 0375 T3("Mo 12:00-15:00, Mo 18:00-24:00", "Mo 12:00-15:00, Mo 18:00-24:00", "Mo 12:00-15:00,18:00-24:00"); 0376 T3("Mo-We,Fr,Su 08:00-13:00", "Mo-We,Fr,Su 08:00-13:00", "Su-We,Fr 08:00-13:00"); 0377 T3("Mo,We,Th,Tu,Sa 08:00-13:00", "Mo,We,Th,Tu,Sa 08:00-13:00", "Mo-Th,Sa 08:00-13:00"); // reordering 0378 T3("Mo-Fr,Tu,We 08:00-13:00", "Mo-Fr,Tu,We 08:00-13:00", "Mo-Fr 08:00-13:00"); // Tu,We already included 0379 T3("Sa-Mo 10:00-23:00, Th 10:00-23:00", "Sa-Mo 10:00-23:00, Th 10:00-23:00", "Sa-Mo,Th 10:00-23:00"); // beginDay > endDay 0380 T3("Sa-Mo 10:00-23:00, Fr 10:00-23:00", "Sa-Mo 10:00-23:00, Fr 10:00-23:00", "Fr-Mo 10:00-23:00"); // beginDay > endDay 0381 T3("Su-Th 10:00-23:00, Fr-Sa 10:00-23:00", "Su-Th 10:00-23:00, Fr-Sa 10:00-23:00", "Mo-Su 10:00-23:00"); // beginDay > endDay 0382 T3("Feb 1-Feb 29 Mo-Su 10:30-20:30; Aug 1-Aug 31 Mo-Fr 10:30-12:00; PH closed", 0383 "Feb 01-29 Mo-Su 10:30-20:30; Aug 01-31 Mo-Fr 10:30-12:00; PH closed", 0384 "Feb Mo-Su 10:30-20:30; Aug Mo-Fr 10:30-12:00; PH closed"); 0385 0386 // complex or creative 24/7 use 0387 T("06:00-01:00 open \"Dining in\" || 24/7 \"Drive-through\""); 0388 T2("Friday and Saturday 24/7 Sunday-Thursday 4:00 am to 12:00 am", "Fr,Sa 00:00-24:00; Su-Th 04:00-24:00"); // bug 445962 0389 // 24/7 as standalone small range selector not supported yet 0390 //T2("Apr-Oct: 24/7; Nov-Mar: Mo-Su 06:00-22:00", "Apr-Oct: 00:00-24:00; Nov-Mar: Mo-Su 06:00-22:00"); 0391 0392 // 4 digit times 0393 T2("0600-1800", "06:00-18:00"); 0394 T2("0700-2000", "07:00-20:00"); 0395 T2("Tu-Th 8:30-17:30, Fr 8:30-1700", "Tu-Th 08:30-17:30, Fr 08:30-17:00"); 0396 #undef T 0397 #undef T2 0398 #undef T3 0399 } 0400 0401 void testSuccess() 0402 { 0403 QFETCH(QByteArray, input); 0404 QFETCH(QByteArray, expectedOutput); 0405 QFETCH(QByteArray, expectedSimplifiedOutput); 0406 OpeningHours oh(input); 0407 QVERIFY(oh.error() != OpeningHours::SyntaxError); 0408 QCOMPARE(oh.normalizedExpression(), expectedOutput); 0409 QCOMPARE(oh.simplifiedExpression(), expectedSimplifiedOutput); 0410 // verify that simplifiedExpression() doesn't alter `oh` 0411 QCOMPARE(oh.normalizedExpression(), expectedOutput); 0412 0413 // verify the expressions we generate are parsed correctly as well 0414 OpeningHours oh2(oh.normalizedExpression()); 0415 QVERIFY(oh2.error() != OpeningHours::SyntaxError); 0416 QCOMPARE(oh2.normalizedExpression(), oh.normalizedExpression()); 0417 0418 OpeningHours oh3(oh.simplifiedExpression()); 0419 QVERIFY(oh3.error() != OpeningHours::SyntaxError); 0420 QCOMPARE(oh3.normalizedExpression(), oh.simplifiedExpression()); 0421 } 0422 0423 void testFail_data() 0424 { 0425 QTest::addColumn<QByteArray>("input"); 0426 QTest::addColumn<OpeningHours::Error>("error"); 0427 0428 #define T(x) QTest::newRow(x) << QByteArray(x) << OpeningHours::SyntaxError 0429 T("23/7"); 0430 T("24/7 geöffnet"); 0431 T("2020-2000"); 0432 T("Jan-Apr 1"); 0433 T("Feb-2020 Apr 1"); 0434 T("Apr 1-Nov"); 0435 T("Su[0]"); 0436 T("Mo[6]"); 0437 T("Mo[-0]"); 0438 T("Tu[-6]"); 0439 T("Mo[0-5]"); 0440 T("We[4-2]"); 0441 T("49:00"); 0442 T("12:61"); 0443 T("60p"); 0444 0445 T("Dec 24-Jan 1,6"); 0446 T("Mo, 1:100"); 0447 0448 // from https://wiki.openstreetmap.org/wiki/Key:opening_hours#Common_mistakes 0449 T("7/8-23"); 0450 T("07;00-2;00pm"); 0451 T("08.00-16.00, public room till 03.00 a.m"); 0452 T("09:00-21:00 TEL/072(360)3200"); 0453 T("Dining in: 6am to 11pm; Drive thru: 24/7"); 0454 T("MWThF: 1200-1800; SaSu: 1200-1700"); 0455 T("BAR: Su-Mo 18:00-02:00; Tu-Th 18:00-03:00; Fr-Sa 18:00-04:00; CLUB: Tu-Th 20:00-03:00; Fr-Sa 20:00-04:00"); 0456 0457 // from https://openingh.openstreetmap.de/evaluation_tool/ 0458 T("00:00-24:00 week 6 Mo-Su Feb; PH off"); 0459 T("monday, Tu, wE, TH 12:00 - 20:00 ; 14:00-16:00 Off ; closed public Holiday"); 0460 0461 // from Osmose, should fail rather than silently drop the last part 0462 T("Mo-Th, Su 17:00-01:00, Fr-Sa 1700:0300"); 0463 0464 // creative uses found in the wild 0465 T("May 01-Jun 15,Sept 01-30 Mo-Fr 10:00-18:00 Sa-Su 09:00-19:00"); 0466 T("Jul 22-Aug 18 2019: Tu-Su 10:00-13:00"); 0467 #undef T 0468 } 0469 0470 void testFail() 0471 { 0472 QFETCH(QByteArray, input); 0473 QFETCH(OpeningHours::Error, error); 0474 OpeningHours oh(input); 0475 QCOMPARE(oh.error(), error); 0476 } 0477 0478 void testValidation_data() 0479 { 0480 QTest::addColumn<QByteArray>("expression"); 0481 QTest::addColumn<OpeningHours::Error>("error"); 0482 0483 QTest::newRow("location") << QByteArray("sunrise-sunset") << OpeningHours::MissingLocation; 0484 #ifdef KOPENINGHOURS_VALIDATOR_ONLY 0485 QTest::newRow("PH") << QByteArray("PH off") << OpeningHours::NoError; 0486 #else 0487 QTest::newRow("PH") << QByteArray("PH off") << OpeningHours::MissingRegion; 0488 #endif 0489 QTest::newRow("SH") << QByteArray("SH off") << OpeningHours::UnsupportedFeature; 0490 QTest::newRow("time interval") << QByteArray("10:00-16:00/90") << OpeningHours::IncompatibleMode; 0491 QTest::newRow("time interval 2") << QByteArray("10:00-16:00/1:30") << OpeningHours::IncompatibleMode; 0492 QTest::newRow("week wrap") << QByteArray("week 45-13") << OpeningHours::UnsupportedFeature; 0493 QTest::newRow("single timepoint") << QByteArray("10:00") << OpeningHours::IncompatibleMode; 0494 QTest::newRow("month timepoint") << QByteArray("Dec 08:00") << OpeningHours::IncompatibleMode; 0495 QTest::newRow("wide range selector comment") << QByteArray("\"Außerhalb der Semesterferien\": Mo-Fr 08:00-22:00; Sa-Su 10:00-20:00; \"Innerhalb der Semesterferien\": Mo-Fr 08:00-18:00; Sa-Su 10:00-16:00;") << OpeningHours::UnsupportedFeature; 0496 0497 QTest::newRow("empty") << QByteArray("") << OpeningHours::Null; 0498 QTest::newRow("empty comment") << QByteArray("\"\"") << OpeningHours::Null; 0499 } 0500 0501 void testValidation() 0502 { 0503 QFETCH(QByteArray, expression); 0504 QFETCH(OpeningHours::Error, error); 0505 0506 OpeningHours oh(expression); 0507 QCOMPARE(oh.error(), error); 0508 (void)oh.normalizedExpression(); // don't crash 0509 (void)oh.simplifiedExpression(); // don't crash 0510 } 0511 }; 0512 0513 QTEST_GUILESS_MAIN(ParserTest) 0514 0515 #include "parsertest.moc"