File indexing completed on 2024-07-14 15:05:10

0001 # -*- coding: utf-8 -*-
0002 #     Copyright 2008-9 Simon Edwards <simon@simonzone.com>
0003 #
0004 # This program is free software; you can redistribute it and/or modify
0005 # it under the terms of the GNU General Public License as published by
0006 # the Free Software Foundation; either version 2 of the License, or
0007 # (at your option) any later version.
0008 #
0009 # This program is distributed in the hope that it will be useful,
0010 # but WITHOUT ANY WARRANTY; without even the implied warranty of
0011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012 # GNU General Public License for more details.
0013 #
0014 # You should have received a copy of the GNU General Public License
0015 # along with this program; if not, write to the
0016 # Free Software Foundation, Inc.,
0017 # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0018 
0019 #
0020 # Unit tests for the .sip file parser.
0021 #
0022 import unittest
0023 import sipparser
0024 import sipsymboldata
0025 import os
0026 import os.path
0027 import subprocess
0028 import re
0029 
0030 def CleanWhitespace(code):
0031     return re.sub(r"\s+"," ",code).strip()
0032 
0033 class TestSipParser(unittest.TestCase):
0034     def setUp(self):
0035         self.parser = sipparser.SipParser()
0036         self.syms = sipsymboldata.SymbolData()
0037         
0038     def mirrorTest(self,code,debugLevel=0):
0039         scope = self.parser.parse(self.syms, code, debugLevel=debugLevel);
0040         new_code = scope.format()
0041         if CleanWhitespace(new_code)!=CleanWhitespace(code):
0042             self.fail("Output code doesn't match input code.\n---- Original:\n" + code + "\n---- Result:\n" + new_code)
0043 
0044     def ioTest(self,incode,outcode,debugLevel=0):
0045         scope = self.parser.parse(self.syms, incode, debugLevel=debugLevel);
0046         new_code = scope.format()
0047         if CleanWhitespace(new_code)!=CleanWhitespace(outcode):
0048             self.fail("Output code doesn't match expected output code.\n---- Expected:\n" + outcode + "\n---- Result:\n" + new_code)
0049 
0050     def strictMirrorTest(self,code,debugLevel=0):
0051         scope = self.parser.parse(self.syms, code, debugLevel=debugLevel);
0052         new_code = scope.format()
0053         if new_code!=code:
0054             self.fail("Output code doesn't match input code.\n---- Original:\n" + code + "\n---- Result:\n" + new_code)
0055 
0056     def simpleParseTest(self,code,debugLevel=0):
0057         self.parser.parse(self.syms, code, debugLevel=debugLevel);
0058 
0059     def testClass0(self):
0060         self.mirrorTest(
0061             """
0062             class Foo {
0063             };
0064             """)
0065 
0066     def testClass1(self):
0067         self.mirrorTest(
0068             """
0069             class Foo {
0070                 Foo ();
0071             };
0072             """)
0073 
0074     def testClass3(self):
0075         self.mirrorTest(
0076             """
0077             class Foo : Bar {
0078             };""")
0079 
0080     def testClass5(self):
0081         self.mirrorTest(
0082             """
0083             class Foo : Bar, Zyzz {
0084             };""")
0085 
0086     def testClass6(self):
0087         self.mirrorTest(
0088             """
0089             class Foo /Abstract/ {
0090             };
0091             """)
0092 
0093     def testClass7(self):
0094         self.mirrorTest(
0095             """
0096             class Foo {
0097                     Foo (int x);
0098                 public:
0099                     Foo ();
0100             };
0101             """)
0102     def testClass8(self):
0103         self.mirrorTest(
0104             """
0105 class ServiceBase : KShared {
0106   ServiceBase (ServiceBasePrivate*const d);
0107 };
0108 """)
0109 
0110     def testOpaqueClass(self):
0111         self.mirrorTest(
0112             """
0113             class OpaqueFoo;
0114             """)
0115 
0116     def testClassVariable(self):
0117         self.mirrorTest(
0118             """
0119             class Foo {
0120                 public:
0121                     int public_x;
0122                 private:
0123                     int private_y;
0124                 protected:
0125                     int protected_z;
0126             };""")
0127 
0128     def testClassVariable2(self):
0129         self.mirrorTest(
0130             """
0131             class Foo {
0132                 public:
0133                     int x = 0;
0134             };""")
0135 
0136     def testClassVariable3(self):
0137         self.mirrorTest(
0138             """
0139             class Foo {
0140                 static int x;
0141                 const int y;
0142             };""")
0143 
0144     def testClassConstructor2(self):
0145         self.mirrorTest(
0146             """
0147             class Foo {
0148                 Foo (int x, int y);
0149             };""")
0150 
0151     def testClassConstructor3(self):
0152         self.mirrorTest(
0153             """
0154             class Foo {
0155                 explicit Foo (int x);
0156             };""")
0157 
0158     def testClassDestructor1(self):
0159         self.mirrorTest(
0160             """
0161             class Foo {
0162                 ~Foo ();
0163             };""")
0164 
0165     def testClassMethod(self):
0166         self.mirrorTest(
0167             """
0168             class Foo {
0169                 int getFooValue (int x);
0170             };""")
0171 
0172     def testClassVirtualMethod(self):
0173         self.mirrorTest(
0174             """
0175             class Foo {
0176                 virtual int getFooValue (int x);
0177             };""")
0178 
0179     def testClassPureVirtualMethod(self):
0180         self.mirrorTest(
0181             """
0182             class Foo {
0183                 virtual int getFooValue (int x)=0;
0184             };""")
0185 
0186     def testFunctions(self):
0187         self.mirrorTest(
0188             """
0189             int DoFoo (int x);
0190             void StopFoo ();
0191             """)
0192 
0193     def testFunctions2(self):
0194         self.mirrorTest(
0195             """
0196             const int* DoFoo (int x);
0197             """)
0198 
0199     def testFunctions3(self):
0200         self.mirrorTest(
0201             """
0202             QString& FooConst () const;
0203             """)
0204 
0205     def testFunctions4(self):
0206         self.mirrorTest(
0207             """
0208             void Foo (unsigned long x);
0209             """)
0210 
0211     def testFunctions5(self):
0212         self.mirrorTest(
0213             """
0214             void Foo (long x [5]);
0215             """)
0216 
0217     def testFunctions6(self):
0218         self.mirrorTest(
0219             """
0220             void* foo (int, double (*doublePtr)(float,QString*));
0221             """)
0222 
0223     def testFunctions7(self):
0224         self.mirrorTest(
0225             """
0226             int DoFoo (int* x /Out/);
0227             """)
0228 
0229     def testFunctions9(self):
0230         self.mirrorTest(
0231             """
0232 KConfigGroup            group (const QByteArray& group);
0233 const KConfigGroup      group (const QByteArray& group);
0234 const KConfigGroup      group (const QByteArray& group) const;
0235             """)
0236 
0237     def testFunctions10(self):
0238         self.mirrorTest(
0239             """
0240 TermPrivate QSharedDataPointer<Nepomuk::Query::TermPrivate>::clone ();
0241             """)
0242 
0243     def testAccess(self):
0244         self.mirrorTest(
0245             """void PlainPreFunc ();
0246 class Foo {
0247     public:
0248         class Bar {
0249                 void privateBar ();
0250         };
0251         void publicFoo ();
0252 };
0253 void PlainPostFunc ();
0254 """)
0255     
0256 
0257     def testFunctionIgnore(self):
0258         self.mirrorTest(
0259             """
0260             void DontIgnoreThisFoo ();
0261             //ig int DoIgnoreMeFoo (int x);
0262             void DontIgnoreThisFoo2 ();
0263             """)
0264         
0265     def testOpaqueClassIgnore(self):
0266         self.mirrorTest(
0267             """
0268             //ig class Foo;
0269             """)
0270         
0271     def testTypedefIgnore(self):
0272         self.mirrorTest(
0273 """
0274 //ig    typedef QList<KProtocolInfo::Ptr> List;                                                                    
0275     static QStringList      protocols ();                                                                          
0276 """)
0277 
0278     def testTypedefIgnore2(self):
0279         self.mirrorTest("""
0280 class KLibrary : QLibrary
0281 {
0282 public:
0283 //ig     typedef void (*void_function_ptr)();
0284 };
0285 """)
0286 
0287     def testOperator1(self):
0288         self.mirrorTest(
0289             """
0290             class Foo {
0291                 bool operator == (int);
0292             };
0293             """)
0294 
0295     def testOperator2(self):
0296         self.mirrorTest(
0297             """
0298             class Foo {
0299                 virtual bool operator == (int);
0300             };
0301             """)
0302 
0303     def testOperator3(self):
0304         self.mirrorTest(
0305             """
0306             class Foo {
0307                 QVariant operator QVariant ();
0308             };
0309             """,debugLevel=0)
0310 
0311     def testNamespace(self):
0312         self.mirrorTest(
0313             """
0314             namespace FooSpace {
0315                 int DoFoo (int x);
0316                 void StopFoo ();
0317             };
0318             """)
0319 
0320     def testEnum(self):
0321         self.mirrorTest(
0322             """
0323             enum global {
0324                 earth,
0325                 orb,
0326                 globe
0327             };
0328             """)
0329 
0330     def testEnum2(self):
0331         self.mirrorTest(
0332             """
0333             enum global {
0334                 earth,
0335                 orb,
0336                 globe,
0337 
0338                 universe
0339             };
0340             """)
0341 
0342     def testEnum3(self):
0343         self.mirrorTest(
0344             """
0345             enum global {
0346 
0347                 // just a comment.
0348                 earth,
0349                 orb,
0350 
0351                 // Wierd stuff.
0352                 globe,
0353                 universe
0354 
0355                 // le fin
0356             };
0357             """)
0358 
0359     def testEnumAnonymous(self):
0360         self.mirrorTest(
0361             """
0362             enum {
0363                 earth,
0364                 orb,
0365                 globe
0366             };
0367             """)
0368 
0369     def testEnumSipIf(self):
0370         self.ioTest(
0371             """
0372 enum {
0373     earth,
0374     // This is a comment
0375 %If (FOO -)
0376     orb,
0377 %End
0378     globe
0379 };
0380 ""","""
0381 enum {
0382     earth,
0383     // This is a comment
0384     orb,
0385     globe
0386 };
0387             """,debugLevel=0)
0388 
0389     def testTypedef1(self):
0390         self.mirrorTest(
0391             """
0392             typedef QString& stringref;
0393             """)
0394     
0395     def testTypedef2(self):
0396         self.mirrorTest(
0397             """typedef QObject** objPtrPtr;
0398             """)
0399 
0400     def testTypedef3(self):
0401         self.mirrorTest(
0402 """
0403 typedef QFlags<KCrash::CrashFlag> CrashFlags;
0404 """)
0405 
0406     def testTypedef4(self):
0407         self.mirrorTest(
0408 """
0409 //ig typedef foo bar;
0410 """)
0411 
0412     def testTypedef5(self):
0413         self.mirrorTest("""
0414 //ig typedef void (*KdeCleanUpFunction)();
0415 """)
0416 
0417     def testSipDirective1(self):
0418         self.mirrorTest(
0419             """
0420 class Foo {
0421     %TypeHeaderCode
0422     #include <kconfigbase.h>
0423     %End
0424 };
0425 """)
0426 
0427     def testMethodCode1(self):
0428         self.mirrorTest(
0429             """
0430 int DoFoo (int x);
0431 %MethodCode
0432 // Method code is here.
0433 
0434 // Ends here.
0435 %End
0436 """)
0437 
0438     def testTemplate(self):
0439         self.mirrorTest(
0440             """
0441             QList<int> intlist;
0442             """)
0443 
0444     def testLineComment1(self):
0445         self.mirrorTest(
0446 """
0447 // Just a line comment.
0448 """)
0449 
0450     def testLineComment2(self):
0451         self.mirrorTest(
0452 """
0453 /* Just a C comment. */
0454 """)
0455 
0456     def testBlankLine(self):
0457         self.mirrorTest(
0458 """
0459 // Start, then blank
0460   
0461 // End
0462 """)
0463 
0464     def testBlankLine2(self):
0465         self.mirrorTest(
0466 """
0467 class Foo {
0468 %ConvertToSubClassCode
0469 
0470 // Subcode...
0471 // End.
0472 %End
0473 };
0474 """)
0475 
0476     def testTemplate(self):
0477         self.mirrorTest(
0478 """
0479 template <Bar>
0480 class Foo {
0481 public:
0482     static QString deref (Bar i);
0483 };
0484 """)
0485 
0486     def testMappedType(self):
0487         self.mirrorTest(
0488 """
0489 %MappedType QMap<Foo,Bar>
0490 {
0491 
0492 };
0493 
0494 """)
0495 
0496     def testMappedType2(self):
0497         self.mirrorTest(
0498 """
0499 template <TYPE1,TYPE2>
0500 %MappedType QMap<TYPE1,TYPE2>
0501 {
0502 
0503 };
0504 
0505 class Foo {
0506 
0507 };
0508 """)
0509 
0510     def testMappedType3(self):
0511      
0512         self.mirrorTest(
0513 """
0514 %MappedType QChar /API=QString:2 - /
0515 {
0516 // Foo
0517 };
0518 """,debugLevel=0)
0519 
0520     def testNestedTemplate(self):
0521         self.mirrorTest(
0522 """
0523 KBookmarkGroup          addBookmarks (const QList<QPair<QString,QString>>& list);
0524 """)
0525 
0526     def testCppSigs1(self):
0527         self.mirrorTest("""
0528 class Foo {
0529         ItemDouble (const QString& _group, const QString& _key, double reference, double defaultValue = 0) [(const QString& _group, const QString& _key, double& reference, double defaultValue = 0)];         
0530 };
0531 """)
0532 
0533     def testCppSigs2(self):
0534         self.mirrorTest("""
0535 class Foo {
0536         int itemDouble (const QString& _group, const QString& _key, double reference, double defaultValue = 0)  [int (const QString& _group, const QString& _key, double& reference, double defaultValue = 0)];         
0537 };
0538 """)
0539     def testCppSigs3(self):
0540         self.mirrorTest("""
0541 class Foo
0542 {
0543     virtual SIP_PYOBJECT    read (qint64 maxlen) /ReleaseGIL/ [qint64 (char* data, qint64 maxlen)];
0544 %MethodCode
0545 // foo.
0546 %End
0547 };
0548 """)
0549 
0550     def testForce(self):
0551         self.mirrorTest("""
0552 class Foo {
0553 public:
0554     Foo ();
0555     int bar ();
0556 //force
0557     int forceBar ();
0558 //end
0559 };
0560 """)
0561 
0562     def testForce2(self):
0563         self.mirrorTest("""
0564 namespace Foo {
0565     int bar ();
0566 //force
0567     int forceBar ();
0568 //end
0569     int bar2 ();
0570 };
0571 """)
0572 
0573     def testArrowDefaults(self):
0574         self.mirrorTest("""
0575 class Foo
0576 {
0577     QString                 label (const QString& language = KGlobal::locale()->language());
0578 };
0579 """)
0580 
0581     def testCTSCC(self):
0582         self.mirrorTest("""
0583 class Foo {
0584 //force
0585 %ConvertToSubClassCode
0586 // Custom %ConvertToSubClassCode
0587 %End
0588 //end
0589 };
0590 """)
0591 
0592     def testTemplateBlocks(self):
0593         text ="""
0594 //
0595 
0596 %ModuleHeaderCode
0597 #include <kaccelgen.h>
0598 %End
0599 
0600 namespace KAccelGen
0601 {
0602 
0603 template <Iter>
0604 class Deref
0605 {
0606 %TypeHeaderCode
0607 #include <kaccelgen.h>
0608 %End
0609 
0610 
0611 public:
0612     static QString          deref (Iter i);
0613 };
0614 // Deref
0615 
0616 
0617 template <Iter>
0618 class Deref_Key
0619 {
0620 %TypeHeaderCode
0621 #include <kaccelgen.h>
0622 %End
0623 
0624 
0625 public:
0626     static QString          deref (Iter i);
0627 };
0628 // Deref_Key
0629 
0630 bool                    isLegalAccelerator (const QString& str, int index);
0631 void                    generate (const QStringList& source, QStringList& target);
0632 };
0633 // KAccelGen
0634 
0635 %ModuleHeaderCode
0636 #include <kaccelgen.h>
0637 %End
0638 """
0639 
0640         self.mirrorTest(text)
0641 
0642 #        scope = self.parser.parse(self.syms, text, debugLevel=0);
0643 #        for item in scope[5]:
0644 #            print(repr(item))
0645 #            print("-----------------------------" + item.format())
0646 
0647 
0648     def testStrict0(self):
0649         self.strictMirrorTest(
0650             """// Foo
0651 
0652 // bar
0653 
0654 %ModuleHeaderCode
0655 //ctscc
0656 dsfd
0657 %End
0658 
0659 
0660 class KUrl : QUrl
0661 {
0662 };
0663 """)
0664 
0665     def testSuperClassQueries(self):
0666         scope = self.parser.parse(self.syms, """
0667 class Bar {};
0668 class Zyzz : Bar {};
0669 class Foo : Zyzz {
0670 
0671 };
0672 """)
0673         bar = self.syms.lookupType("Bar",scope)
0674         self.assertTrue(bar is not None)
0675         self.assertTrue(bar.allSuperClassNames() is not None)
0676         self.assertTrue(len(bar.allSuperClassNames())==0)
0677         foo = self.syms.lookupType("Foo",scope)
0678         self.assertTrue(foo is not None)
0679         fooBases = foo.allSuperClassNames()
0680         self.assertTrue(fooBases is not None)
0681         self.assertTrue(len(fooBases)==2)
0682 
0683     def testSipStmt(self):
0684         scope = self.parser.parse(self.syms, """
0685 template<TYPE1, TYPE2>
0686 %MappedType QHash<TYPE1, TYPE2> /DocType="dict-of-TYPE1-TYPE2"/
0687 {
0688 
0689 };
0690 
0691 """,debugLevel=0)
0692 
0693     def testModule(self):
0694         self.mirrorTest("""
0695 %Module PyKDE4.kdecore
0696 """)
0697 
0698     def testModule2(self):
0699         self.mirrorTest("""
0700 %Module(name=PyQt4.QtCore, keyword_arguments="Optional")
0701 
0702 %Timeline {Qt_4_1_1 Qt_4_1_2}""")
0703 
0704     def testAPI(self):
0705         self.simpleParseTest("""
0706 %API(name=QDate, version=2)
0707 """)
0708 
0709     def testInclude(self):
0710         self.simpleParseTest("""
0711 %Include(name=staticplugins.sip, optional=True)
0712 """)
0713 
0714     def testGetter(self):
0715         # This just has to go through the parser. PyKDE doesn't need the info which is read in.
0716         self.simpleParseTest("""
0717 class Foo {
0718 public:
0719     static const QMetaObject staticMetaObject {
0720 %GetCode
0721     sipPy = qpycore_qobject_staticmetaobject(sipPyType);
0722 %End
0723 };
0724 };
0725 """)
0726 
0727     def testQListSubclass(self):
0728         self.simpleParseTest("""
0729 class AddresseeList : QList<Addressee>
0730 {
0731 };
0732 """)
0733 
0734     def testEnumAnnotation(self):
0735         self.simpleParseTest("""enum Command
0736 {
0737     None /PyName=None_/,
0738     SetTransferMode,
0739     SetProxy,
0740     ConnectToHost
0741 };
0742 """)
0743 
0744 
0745 
0746     def xtestQtCoremod(self):
0747         with open("/usr/share/sip/PyQt4/QtCore/QtCoremod.sip") as fhandle:
0748             text = fhandle.read()
0749         scope = self.parser.parse(self.syms, text)
0750         print(scope.format())
0751 
0752     def xtestFullCompare(self):
0753         sipdir = "/home/sbe/devel/svn/kde/branches/KDE/4.4/kdebindings/python/pykde4/sip/kdeui/"
0754         #sipdir = "/usr/share/sip/PyQt4/QtGui/"        
0755         for filename in os.listdir(sipdir):
0756             print(filename)
0757             if filename.endswith(".sip"):
0758                 filepath = os.path.join(sipdir,filename) 
0759                 with open(filepath) as fhandle:
0760                     text = fhandle.read()
0761                 self.syms = sipsymboldata.SymbolData()
0762                 scope = self.parser.parse(self.syms, text)
0763 
0764                 output = scope.format()
0765                 if CleanWhitespace(text)!=CleanWhitespace(output):
0766                     with open(filename+".v2",'w') as outhandle:
0767                         outhandle.write(scope.format())
0768                     subprocess.call(['diff','-durb',filepath,filename+".v2"])
0769 
0770 #        self.parser = sipparser.SipParser()
0771 
0772 #    def parse(self,text):
0773 #        self.parser.parse(self.symbol_data, self.state_info, text,2 if debug else 1)
0774 '''
0775     def testEmpty(self):
0776         self.parse("")
0777 
0778     def testCComments(self):
0779         self.parse("""
0780 
0781 
0782 /* A C style comment */
0783 
0784 /*
0785 Multiline
0786 */
0787 
0788 
0789 // single
0790 /*
0791 muliple
0792 */
0793 """)
0794 
0795     def testMappedTypeConstType(self):
0796         self.parse("""
0797 %MappedType QList<const Soprano::Backend*>
0798 {
0799 %TypeHeaderCode
0800 #include <qlist.h>
0801 %End
0802 
0803 %ConvertFromTypeCode
0804     // Create the list.
0805 %End
0806 
0807 %ConvertToTypeCode
0808     // Check the type if that is all that is required.
0809 
0810 %End
0811 };
0812 
0813 """)
0814 
0815 '''
0816 if __name__ == '__main__':
0817     unittest.main()