File indexing completed on 2024-12-01 13:02:57
0001 #!env python3 0002 # -*- coding: utf-8 -*- 0003 # Copyright 2009 Simon Edwards <simon@simonzone.com> 0004 # 0005 # This program is free software; you can redistribute it and/or modify 0006 # it under the terms of the GNU General Public License as published by 0007 # the Free Software Foundation; either version 2 of the License, or 0008 # (at your option) any later version. 0009 # 0010 # This program is distributed in the hope that it will be useful, 0011 # but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 # GNU General Public License for more details. 0014 # 0015 # You should have received a copy of the GNU General Public License 0016 # along with this program; if not, write to the 0017 # Free Software Foundation, Inc., 0018 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0019 0020 import unittest 0021 import cppparser 0022 import cppsymboldata 0023 import qtkdemacros 0024 import re 0025 0026 def CleanWhitespace(code): 0027 return re.sub(r"\s+"," ",code).strip() 0028 0029 class TestCppParser(unittest.TestCase): 0030 0031 def setUp(self): 0032 self.parser = cppparser.CppParser() 0033 self.syms = cppsymboldata.SymbolData() 0034 0035 def mirrorTest(self,code,debugLevel=0): 0036 scope = self.parser.parse(self.syms, code, debugLevel=debugLevel); 0037 new_code = scope.format() 0038 if CleanWhitespace(new_code)!=CleanWhitespace(code): 0039 self.fail("Output code doesn't match input code.\n---- Original:\n" + code + "\n---- Result:\n" + new_code) 0040 0041 def ioTest(self,incode,outcode,debugLevel=0): 0042 scope = self.parser.parse(self.syms, incode, debugLevel=debugLevel); 0043 new_code = scope.format() 0044 if CleanWhitespace(new_code)!=CleanWhitespace(outcode): 0045 self.fail("Output code doesn't match expected output code.\n---- Expected:\n" + outcode + "\n---- Result:\n" + new_code) 0046 0047 def testClass1(self): 0048 self.mirrorTest( 0049 """ 0050 class Foo { 0051 }; 0052 """) 0053 0054 def testClass2(self): 0055 self.ioTest( 0056 """ 0057 class Foo { 0058 public: 0059 };""",""" 0060 class Foo { 0061 };""") 0062 0063 def testClass3(self): 0064 self.ioTest( 0065 """ 0066 class Foo : public Bar { 0067 };""",""" 0068 class Foo : Bar { 0069 };""") 0070 0071 def testClass4(self): 0072 self.ioTest( 0073 """ 0074 class Foo : private Bar { 0075 };""",""" 0076 class Foo : Bar { 0077 };""") 0078 0079 def testClass5(self): 0080 self.mirrorTest( 0081 """ 0082 class Foo : Bar, Zyzz { 0083 };""") 0084 0085 def testClass6(self): 0086 self.mirrorTest( 0087 """ 0088 class OpaqueFoo; 0089 """) 0090 0091 def testClassVariable(self): 0092 self.mirrorTest( 0093 """ 0094 class Foo { 0095 public: 0096 int public_x; 0097 private: 0098 int private_y; 0099 protected: 0100 int protected_z; 0101 };""") 0102 0103 def testClassVariable2(self): 0104 self.mirrorTest( 0105 """ 0106 class Foo { 0107 public: 0108 int x = 0; 0109 };""") 0110 0111 def testClassVariable3(self): 0112 self.mirrorTest( 0113 """ 0114 class Foo { 0115 static int x; 0116 const int y; 0117 };""") 0118 0119 def testClassConstructor(self): 0120 self.mirrorTest( 0121 """ 0122 class Foo { 0123 Foo (); 0124 };""") 0125 0126 def testClassConstructor2(self): 0127 self.mirrorTest( 0128 """ 0129 class Foo { 0130 Foo (int x, int y); 0131 };""") 0132 0133 def testClassConstructor3(self): 0134 self.mirrorTest( 0135 """ 0136 class Foo { 0137 explicit Foo (int x); 0138 };""") 0139 0140 def testClassConstructor4(self): 0141 self.mirrorTest( 0142 """ 0143 class Foo { 0144 public: 0145 Foo (); 0146 private: 0147 Foo (int x); 0148 };""") 0149 0150 def testClassDestructor1(self): 0151 self.mirrorTest( 0152 """ 0153 class Foo { 0154 ~Foo (); 0155 };""") 0156 0157 def testClassMethod(self): 0158 self.mirrorTest( 0159 """ 0160 class Foo { 0161 int getFooValue (int x); 0162 };""") 0163 0164 def testClassVirtualMethod(self): 0165 self.mirrorTest( 0166 """ 0167 class Foo { 0168 virtual int getFooValue (int x); 0169 };""") 0170 0171 def testClassPureVirtualMethod(self): 0172 self.mirrorTest( 0173 """ 0174 class Foo { 0175 virtual int getFooValue (int x)=0; 0176 };""") 0177 0178 def testFunctions(self): 0179 self.mirrorTest( 0180 """ 0181 int DoFoo (int x); 0182 void StopFoo (); 0183 """) 0184 0185 def testFunctions2(self): 0186 self.mirrorTest( 0187 """ 0188 const int* DoFoo (int x); 0189 """) 0190 0191 def testFunctions3(self): 0192 self.mirrorTest( 0193 """ 0194 QString& FooConst () const; 0195 """) 0196 0197 def testFunctions4(self): 0198 self.mirrorTest( 0199 """ 0200 void Foo (unsigned long x); 0201 """) 0202 0203 def testFunctions5(self): 0204 self.mirrorTest( 0205 """ 0206 void Foo (long x [5]); 0207 """) 0208 0209 # def testFunctions6(self): 0210 # self.ioTest( 0211 # """ 0212 # void* foo (int, double (*doublePtr)(float, QString*)); 0213 # """,""" 0214 # void* foo (int, $fpdouble (* doublePtr = float,QString*); 0215 # """) 0216 0217 def testFunctions7(self): 0218 self.mirrorTest( 0219 """ 0220 template <T> 0221 void foo (T t); 0222 """) 0223 0224 def testFunctions8(self): 0225 self.ioTest( 0226 """template<typename T> 0227 inline T readCheck(const char *key, const T &defaultValue) const; 0228 ""","""template <T> 0229 T readCheck (const char* key, const T& defaultValue) const; 0230 """) 0231 0232 def testFunctions9(self): 0233 self.mirrorTest( 0234 """ 0235 KConfigGroup group (const QByteArray& group); 0236 const KConfigGroup group (const QByteArray& group); 0237 const KConfigGroup group (const QByteArray& group) const; 0238 """) 0239 0240 def testFunctions10(self): 0241 self.ioTest("""int downloadRegionDialog(WindowFlags const f = 0);""", 0242 """ int downloadRegionDialog (const WindowFlags f = 0);""") 0243 0244 def testOperator1(self): 0245 self.mirrorTest( 0246 """ 0247 class Foo { 0248 bool operator== (int); 0249 }; 0250 """) 0251 0252 def testNamespace(self): 0253 self.mirrorTest( 0254 """ 0255 namespace FooSpace 0256 { 0257 int DoFoo (int x); 0258 void StopFoo (); 0259 }; 0260 """) 0261 0262 def testEnum(self): 0263 self.mirrorTest( 0264 """ 0265 enum global { 0266 earth, 0267 orb, 0268 globe 0269 }; 0270 """) 0271 0272 def testEnumInClass(self): 0273 self.ioTest( 0274 """ 0275 enum TimeFormatOption { 0276 TimeDefault = 0x0, ///< Default formatting using seconds and the format 0277 ///< as specified by the locale. 0278 TimeDuration = 0x6 ///< Read/format time string as duration. This will strip 0279 }; 0280 """,""" 0281 enum TimeFormatOption { 0282 TimeDefault=0x0, 0283 TimeDuration=0x6 0284 }; 0285 """) 0286 0287 def testNamespaceEnum(self): 0288 self.mirrorTest( 0289 """ 0290 namespace Foo { 0291 0292 const KComponentData& mainComponent (); 0293 0294 enum global { 0295 earth, 0296 orb, 0297 globe 0298 }; 0299 }; 0300 """) 0301 0302 def testEnumAnonymous(self): 0303 self.mirrorTest( 0304 """ 0305 enum { 0306 earth, 0307 orb, 0308 globe 0309 }; 0310 """) 0311 0312 def testFriendClass(self): 0313 self.ioTest( 0314 """ 0315 class Foo { 0316 friend class Bar; 0317 }; 0318 """,""" 0319 class Foo { 0320 }; 0321 """) 0322 0323 def testTypedef1(self): 0324 self.mirrorTest( 0325 """ 0326 typedef QString& stringref; 0327 """) 0328 0329 def testTypedef2(self): 0330 self.ioTest( 0331 """ 0332 typedef enum simple {easy, bobsyouruncle, noproblem}; 0333 """,""" 0334 typedef enum 0335 { 0336 easy, 0337 bobsyouruncle, 0338 noproblem 0339 } simple; 0340 """) 0341 0342 def testTypedef3(self): 0343 self.mirrorTest( 0344 """typedef QObject** objPtrPtr; 0345 """) 0346 0347 def testTypedef4(self): 0348 self.mirrorTest( 0349 """typedef QObject* (*CreateInstanceFunction)(QWidget*,QObject*,const QVariantList&); 0350 """) 0351 0352 def testTypedef5(self): 0353 self.mirrorTest( 0354 """typedef QFlags<SearchOption> SearchOptions; 0355 """) 0356 0357 def testTypedef6(self): 0358 self.mirrorTest( 0359 """typedef enum { Name, FromUrl } FileNameUsedForCopying; 0360 """) 0361 0362 def testTypedef7(self): 0363 self.mirrorTest( 0364 """typedef enum { Name, FromUrl } FileNameUsedForCopying; 0365 """) 0366 0367 def testTemplate(self): 0368 self.mirrorTest( 0369 """ 0370 QList<int> intlist; 0371 """) 0372 0373 def testInline(self): 0374 self.ioTest( 0375 """ 0376 inline operator bool() const { return ( d != 0 ); } 0377 """,""" 0378 bool operator bool () const; 0379 """) 0380 0381 def testInline2(self): 0382 self.ioTest( 0383 """ 0384 inline bool TileId::operator==( TileId const& rhs ) const 0385 { 0386 return m_zoomLevel == rhs.m_zoomLevel 0387 && m_tileX == rhs.m_tileX 0388 && m_tileY == rhs.m_tileY 0389 && m_mapThemeIdHash == rhs.m_mapThemeIdHash; 0390 }""", """ 0391 bool TileId:: operator== (const TileId& rhs) const; 0392 """) 0393 0394 def testMacro(self): 0395 self.parser.bareMacros = ["Q_OBJECT"] 0396 self.ioTest( 0397 """ 0398 class FooWidget : public QObject { 0399 Q_OBJECT 0400 public: 0401 FooWidget(); 0402 }; 0403 """, """ 0404 class FooWidget : QObject { 0405 Q_OBJECT 0406 public: 0407 FooWidget (); 0408 }; 0409 """) 0410 0411 def testMacro2(self): 0412 self.parser.bareMacros = ["FOO_EXPORT"] 0413 self.mirrorTest( 0414 """ 0415 class FOO_EXPORT FooWidget { 0416 }; 0417 """) 0418 0419 def testMacro3(self): 0420 self.parser.macros = ["Q_DISABLE_COPY"] 0421 self.mirrorTest( 0422 """ 0423 class FooWidget { 0424 public: 0425 Foo (); 0426 private: 0427 Q_DISABLE_COPY(FooWidget) 0428 }; 0429 """) 0430 0431 def testMacro4(self): 0432 self.parser.bareMacros = ["KGGZMOD_EXPORT"] 0433 self.mirrorTest( 0434 """ 0435 class Module 0436 { 0437 public: 0438 Module (const QString& name); 0439 ~Module (); 0440 0441 enum State 0442 { 0443 created, 0444 done 0445 }; 0446 }; 0447 """) 0448 0449 def testBitfield(self): 0450 self.mirrorTest( 0451 """ 0452 bool mHasMin : 1; 0453 """,debugLevel=0) 0454 0455 def testAccess(self): 0456 self.mirrorTest( 0457 """void PlainPreFunc (); 0458 class Foo { 0459 public: 0460 class Bar { 0461 void privateBar (); 0462 }; 0463 void publicFoo (); 0464 }; 0465 void PlainPostFunc (); 0466 """) 0467 0468 def testMacro4(self): 0469 self.parser.bareMacros = ["Q_OBJECT"] 0470 self.parser.macros = ["Q_PROPERTY"] 0471 self.ioTest( 0472 """ 0473 class AbstractRunner : public QObject 0474 { 0475 Q_OBJECT 0476 Q_PROPERTY(bool matchingSuspended READ isMatchingSuspended WRITE suspendMatching NOTIFY matchingSuspend) 0477 Q_PROPERTY(QString id READ id); 0478 }; 0479 """,""" 0480 class AbstractRunner : QObject 0481 { 0482 Q_OBJECT 0483 Q_PROPERTY(bool matchingSuspended READ isMatchingSuspended WRITE suspendMatching NOTIFY matchingSuspend) 0484 Q_PROPERTY(QString id READ id) 0485 }; 0486 """) 0487 0488 def testFunnyNamespace(self): 0489 self.mirrorTest( 0490 """ 0491 class KJob; 0492 namespace KIO 0493 { 0494 class Job; 0495 }; 0496 class KAutoMountPrivate; 0497 """) 0498 0499 def testNestedTemplate(self): 0500 self.mirrorTest( 0501 """ 0502 KBookmarkGroup addBookmarks (const QList<QPair<QString,QString>>& list); 0503 """) 0504 0505 def testOperatorQUrlConst(self): 0506 self.ioTest( 0507 """ 0508 class Foo { 0509 void reset( bool recursive = false ); 0510 operator QUrl() const { return uri(); } 0511 bool operator==( const Entity& other ) const; 0512 }; 0513 """,""" 0514 class Foo { 0515 void reset (bool recursive = false); 0516 QUrl operator QUrl () const; 0517 bool operator== (const Entity& other) const; 0518 }; 0519 """) 0520 0521 def testPureVirtualDestructor(self): 0522 self.mirrorTest( 0523 """ 0524 class Foo { 0525 public: 0526 Foo (); 0527 virtual ~Foo ()=0; 0528 }; 0529 0530 """) 0531 0532 def testComments(self): 0533 self.mirrorTest( 0534 """ 0535 class Foo { 0536 /** 0537 * bar docs. 0538 */ 0539 public: 0540 void bar (); 0541 }; 0542 0543 """) 0544 0545 def testPrivateSignalHack(self): 0546 text = """ 0547 class KJob : public QObject 0548 { 0549 Q_OBJECT 0550 Q_ENUMS( KillVerbosity Capability Unit ) 0551 Q_FLAGS( Capabilities ) 0552 0553 public: 0554 0555 public Q_SLOTS: 0556 bool suspend(); 0557 0558 protected: 0559 virtual bool doKill(); 0560 0561 public: 0562 bool exec(); 0563 0564 Q_SIGNALS: 0565 #ifndef Q_MOC_RUN 0566 #ifndef DOXYGEN_SHOULD_SKIP_THIS 0567 private: // don't tell moc or doxygen, but those signals are in fact private 0568 #endif 0569 #endif 0570 void result(KJob *job); 0571 }; 0572 """ 0573 self.parser.bareMacros = qtkdemacros.QtBareMacros() 0574 self.parser.macros = qtkdemacros.QtMacros() 0575 self.parser.preprocessorSubstitutionMacros = qtkdemacros.QtPreprocessSubstitutionMacros() 0576 scope = self.parser.parse(self.syms, text) 0577 #print(scope.format()) 0578 0579 0580 #def testLiveAmmo(self): 0581 # with open("/home/sbe/devel/svn/kde/trunk/KDE/kdelibs/kdecore/jobs/kjob.h") as fhandle: 0582 # text = fhandle.read() 0583 # self.parser.bareMacros = qtkdemacros.QtBareMacros(["KDECORE_EXPORT","KDE_EXPORT","KIO_EXPORT","KDE_DEPRECATED", "KDECORE_EXPORT_DEPRECATED"]) 0584 # self.parser.macros = qtkdemacros.QtMacros() 0585 # self.parser.preprocessorSubstitutionMacros = qtkdemacros.QtPreprocessSubstitutionMacros() 0586 # scope = self.parser.parse(self.syms, text) 0587 # print(scope.format()) 0588 0589 def testFriendOperator(self): 0590 self.ioTest( 0591 """ 0592 class GeoDataLatLonAltBox : public GeoDataLatLonBox 0593 { 0594 friend bool operator == ( GeoDataLatLonAltBox const& lhs, GeoDataLatLonAltBox const& rhs); 0595 }; 0596 """,""" 0597 class GeoDataLatLonAltBox : GeoDataLatLonBox 0598 { 0599 bool operator== (const GeoDataLatLonAltBox& lhs, const GeoDataLatLonAltBox& rhs); 0600 }; 0601 """) 0602 0603 # def testFriendOperator2(self): 0604 # self.parser.bareMacros = qtkdemacros.QtBareMacros(["KDECORE_EXPORT"]) 0605 # self.mirrorTest(""" 0606 # class Foo { 0607 # static KDateTime realCurrentLocalDateTime(); 0608 # friend QDataStream KDECORE_EXPORT &operator<<(QDataStream &out, const KDateTime &dateTime); 0609 # friend QDataStream KDECORE_EXPORT &operator>>(QDataStream &in, KDateTime &dateTime); 0610 # }; 0611 # """) 0612 0613 if __name__ == '__main__': 0614 unittest.main()