File indexing completed on 2024-12-08 07:21:24

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()