LCOV - code coverage report
Current view: top level - vcl/qa/cppunit - lifecycle.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 145 161 90.1 %
Date: 2015-06-13 12:38:46 Functions: 85 90 94.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include <unotest/filters-test.hxx>
      11             : #include <test/bootstrapfixture.hxx>
      12             : 
      13             : #include <vcl/wrkwin.hxx>
      14             : #include <vcl/button.hxx>
      15             : #include <vcl/edit.hxx>
      16             : #include <vcl/combobox.hxx>
      17             : #include <vcl/field.hxx>
      18             : #include <vcl/virdev.hxx>
      19             : #include <vcl/tabctrl.hxx>
      20             : #include <vcl/dialog.hxx>
      21             : #include <vcl/layout.hxx>
      22             : #include <vcl/svapp.hxx>
      23             : 
      24          18 : class LifecycleTest : public test::BootstrapFixture
      25             : {
      26             :     void testWidgets(vcl::Window *pParent);
      27             : 
      28             : public:
      29           9 :     LifecycleTest() : BootstrapFixture(true, false) {}
      30             : 
      31             :     void testCast();
      32             :     void testVirtualDevice();
      33             :     void testMultiDispose();
      34             :     void testIsolatedWidgets();
      35             :     void testParentedWidgets();
      36             :     void testChildDispose();
      37             :     void testPostDispose();
      38             :     void testFocus();
      39             :     void testLeakage();
      40             : 
      41           2 :     CPPUNIT_TEST_SUITE(LifecycleTest);
      42           1 :     CPPUNIT_TEST(testCast);
      43           1 :     CPPUNIT_TEST(testVirtualDevice);
      44           1 :     CPPUNIT_TEST(testMultiDispose);
      45           1 :     CPPUNIT_TEST(testIsolatedWidgets);
      46           1 :     CPPUNIT_TEST(testParentedWidgets);
      47           1 :     CPPUNIT_TEST(testChildDispose);
      48           1 :     CPPUNIT_TEST(testPostDispose);
      49           1 :     CPPUNIT_TEST(testFocus);
      50           1 :     CPPUNIT_TEST(testLeakage);
      51           5 :     CPPUNIT_TEST_SUITE_END();
      52             : };
      53             : 
      54             : // A compile time sanity check
      55           1 : void LifecycleTest::testCast()
      56             : {
      57           1 :     ScopedVclPtrInstance< PushButton > xButton( nullptr, 0 );
      58           2 :     ScopedVclPtr<vcl::Window> xWindow(xButton);
      59             : 
      60           2 :     ScopedVclPtrInstance< MetricField > xField( nullptr, 0 );
      61           2 :     ScopedVclPtr<SpinField> xSpin(xField);
      62           2 :     ScopedVclPtr<Edit> xEdit(xField);
      63             : 
      64             : // the following line should NOT compile
      65             : //    VclPtr<PushButton> xButton2(xWindow);
      66           1 : }
      67             : 
      68           1 : void LifecycleTest::testVirtualDevice()
      69             : {
      70           1 :     VclPtr<VirtualDevice> pVDev = VclPtr< VirtualDevice >::Create();
      71           2 :     ScopedVclPtrInstance< VirtualDevice > pVDev2;
      72           2 :     VclPtrInstance<VirtualDevice> pVDev3;
      73           2 :     VclPtrInstance<VirtualDevice> pVDev4( 1 );
      74           2 :     CPPUNIT_ASSERT(!!pVDev && !!pVDev2 && !!pVDev3 && !!pVDev4);
      75           1 : }
      76             : 
      77           1 : void LifecycleTest::testMultiDispose()
      78             : {
      79           1 :     VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
      80           1 :     CPPUNIT_ASSERT(xWin.get() != NULL);
      81           1 :     xWin->disposeOnce();
      82           1 :     xWin->disposeOnce();
      83           1 :     xWin->disposeOnce();
      84           1 :     CPPUNIT_ASSERT(xWin->GetWindow(GetWindowType::Parent) == NULL);
      85           1 :     CPPUNIT_ASSERT(xWin->GetChild(0) == NULL);
      86           1 :     CPPUNIT_ASSERT(xWin->GetChildCount() == 0);
      87           1 : }
      88             : 
      89           2 : void LifecycleTest::testWidgets(vcl::Window *pParent)
      90             : {
      91           2 :     { ScopedVclPtrInstance< PushButton > aPtr( pParent );   }
      92           2 :     { ScopedVclPtrInstance< OKButton > aPtr( pParent );     }
      93           2 :     { ScopedVclPtrInstance< CancelButton > aPtr( pParent ); }
      94           2 :     { ScopedVclPtrInstance< HelpButton > aPtr( pParent );   }
      95             : 
      96             :     // Some widgets really insist on adoption.
      97           2 :     if (pParent)
      98             :     {
      99           1 :         { ScopedVclPtrInstance< CheckBox > aPtr( pParent );     }
     100           1 :         { ScopedVclPtrInstance< Edit > aPtr( pParent );         }
     101           1 :         { ScopedVclPtrInstance< ComboBox > aPtr( pParent );     }
     102           1 :         { ScopedVclPtrInstance< RadioButton > aPtr( pParent );  }
     103             :     }
     104           2 : }
     105             : 
     106           1 : void LifecycleTest::testIsolatedWidgets()
     107             : {
     108           1 :     testWidgets(NULL);
     109           1 : }
     110             : 
     111           1 : void LifecycleTest::testParentedWidgets()
     112             : {
     113           1 :     ScopedVclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
     114           1 :     CPPUNIT_ASSERT(xWin.get() != NULL);
     115           1 :     xWin->Show();
     116           1 :     testWidgets(xWin);
     117           1 : }
     118             : 
     119             : class DisposableChild : public vcl::Window
     120             : {
     121             : public:
     122           1 :     explicit DisposableChild(vcl::Window *pParent) : vcl::Window(pParent) {}
     123           2 :     virtual ~DisposableChild()
     124           2 :     {
     125           1 :         disposeOnce();
     126           2 :     }
     127             : };
     128             : 
     129           1 : void LifecycleTest::testChildDispose()
     130             : {
     131           1 :     VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
     132           1 :     CPPUNIT_ASSERT(xWin.get() != NULL);
     133           2 :     VclPtrInstance< DisposableChild > xChild( xWin.get() );
     134           1 :     xWin->Show();
     135           1 :     xChild->disposeOnce();
     136           2 :     xWin->disposeOnce();
     137           1 : }
     138             : 
     139           1 : void LifecycleTest::testPostDispose()
     140             : {
     141           1 :     VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
     142           1 :     xWin->disposeOnce();
     143             : 
     144             :     // check selected methods continue to work post-dispose
     145           1 :     CPPUNIT_ASSERT(!xWin->GetParent());
     146           1 :     xWin->Show();
     147           1 :     CPPUNIT_ASSERT(!xWin->IsReallyShown());
     148           1 :     CPPUNIT_ASSERT(!xWin->IsEnabled());
     149           1 :     CPPUNIT_ASSERT(!xWin->IsInputEnabled());
     150           1 :     CPPUNIT_ASSERT(!xWin->GetChild(0));
     151           1 :     CPPUNIT_ASSERT(!xWin->GetWindow(GetWindowType::Parent));
     152           1 : }
     153             : 
     154           2 : class FocusCrashPostDispose : public TabControl
     155             : {
     156             : public:
     157           1 :     explicit FocusCrashPostDispose(vcl::Window *pParent) :
     158           1 :         TabControl(pParent, 0)
     159             :     {
     160           1 :     }
     161           0 :     virtual bool PreNotify( NotifyEvent& ) SAL_OVERRIDE
     162             :     {
     163           0 :         return false;
     164             :     }
     165           0 :     virtual bool Notify( NotifyEvent& ) SAL_OVERRIDE
     166             :     {
     167           0 :         return false;
     168             :     }
     169           0 :     virtual void GetFocus() SAL_OVERRIDE
     170             :     {
     171           0 :         CPPUNIT_FAIL("get focus");
     172           0 :     }
     173           0 :     virtual void LoseFocus() SAL_OVERRIDE
     174             :     {
     175           0 :         CPPUNIT_FAIL("this should never be called");
     176           0 :     }
     177             : };
     178             : 
     179           1 : void LifecycleTest::testFocus()
     180             : {
     181           1 :     ScopedVclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
     182           2 :     ScopedVclPtrInstance< FocusCrashPostDispose > xChild(xWin);
     183           1 :     xWin->Show();
     184           1 :     xChild->GrabFocus();
     185             :     // process asynchronous ToTop
     186           2 :     Scheduler::ProcessTaskScheduling(false);
     187             :     // FIXME: really awful to test focus issues without showing windows.
     188             :     // CPPUNIT_ASSERT(xChild->HasFocus());
     189           1 : }
     190             : 
     191             : template <class vcl_type>
     192             : class LeakTestClass : public vcl_type
     193             : {
     194             :     bool &mrDeleted;
     195             : public:
     196             :     template<typename... Arg>
     197          13 :         LeakTestClass(bool &bDeleted, Arg &&... arg) :
     198          15 :             vcl_type(std::forward<Arg>(arg)...),
     199          15 :             mrDeleted(bDeleted)
     200             :     {
     201          13 :         mrDeleted = false;
     202          13 :     }
     203          26 :     ~LeakTestClass()
     204             :     {
     205          13 :         mrDeleted = true;
     206          39 :     }
     207             : };
     208             : 
     209          13 : class LeakTestObject
     210             : {
     211             :     bool                mbDeleted;
     212             :     VclPtr<vcl::Window> mxRef;
     213             :     void               *mpRef;
     214          13 :     LeakTestObject() {}
     215             : public:
     216             :     template<typename vcl_type, typename... Arg> static LeakTestObject *
     217          13 :         Create(Arg &&... arg)
     218             :     {
     219          13 :         LeakTestObject *pNew = new LeakTestObject();
     220          13 :         pNew->mxRef = VclPtr< LeakTestClass< vcl_type > >::Create( pNew->mbDeleted,
     221          13 :                                                                    std::forward<Arg>(arg)...);
     222          13 :         pNew->mpRef = static_cast<void *>(static_cast<vcl::Window *>(pNew->mxRef));
     223          13 :         return pNew;
     224             :     }
     225          16 :     VclPtr<vcl::Window> getRef() { return mxRef; }
     226          13 :     void disposeAndClear()
     227             :     {
     228          13 :         mxRef.disposeAndClear();
     229          13 :     }
     230          13 :     void assertDeleted()
     231             :     {
     232          13 :         if (!mbDeleted)
     233             :         {
     234           0 :             OUStringBuffer aMsg = "Type '";
     235           0 :             vcl::Window *pWin = static_cast<vcl::Window *>(mpRef);
     236           0 :             aMsg.appendAscii(typeid(*pWin).name());
     237           0 :             aMsg.append("' not freed after dispose");
     238           0 :             CPPUNIT_FAIL(OUStringToOString(aMsg.makeStringAndClear(),
     239           0 :                                            RTL_TEXTENCODING_UTF8).getStr());
     240             :         }
     241          13 :     }
     242             : };
     243             : 
     244           1 : void LifecycleTest::testLeakage()
     245             : {
     246           1 :     std::vector<LeakTestObject *> aObjects;
     247             : 
     248             :     // Create objects
     249           1 :     aObjects.push_back(LeakTestObject::Create<WorkWindow>(nullptr, WB_APP|WB_STDWORK));
     250           2 :     VclPtr<vcl::Window> xParent = aObjects.back()->getRef();
     251             : 
     252           1 :     aObjects.push_back(LeakTestObject::Create<PushButton>(xParent));
     253           1 :     aObjects.push_back(LeakTestObject::Create<OKButton>(xParent));
     254           1 :     aObjects.push_back(LeakTestObject::Create<CancelButton>(xParent));
     255           1 :     aObjects.push_back(LeakTestObject::Create<HelpButton>(xParent));
     256           1 :     aObjects.push_back(LeakTestObject::Create<CheckBox>(xParent));
     257           1 :     aObjects.push_back(LeakTestObject::Create<Edit>(xParent));
     258           1 :     aObjects.push_back(LeakTestObject::Create<ComboBox>(xParent));
     259           1 :     aObjects.push_back(LeakTestObject::Create<RadioButton>(xParent));
     260             : 
     261             :     { // something that looks like a dialog
     262           1 :         aObjects.push_back(LeakTestObject::Create<Dialog>(xParent,WB_CLIPCHILDREN|WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE|WB_SIZEABLE));
     263           1 :         VclPtr<vcl::Window> xDlgParent = aObjects.back()->getRef();
     264           1 :         aObjects.push_back(LeakTestObject::Create<VclVBox>(xDlgParent));
     265           2 :         VclPtr<vcl::Window> xVBox = aObjects.back()->getRef();
     266           2 :         aObjects.push_back(LeakTestObject::Create<VclVButtonBox>(xVBox));
     267             :     }
     268             : 
     269             : #if 0 // FIXME - would be good to get internal paths working.
     270             :     aObjects.push_back(LeakTestObject::Create<ModelessDialog>(xParent, "PrintProgressDialog", "vcl/ui/printprogressdialog.ui"));
     271             : #endif
     272           1 :     aObjects.push_back(LeakTestObject::Create<ModalDialog>(xParent));
     273           1 :     xParent.clear();
     274             : 
     275          14 :     for (auto i = aObjects.rbegin(); i != aObjects.rend(); ++i)
     276          13 :         (*i)->getRef()->Show();
     277             : 
     278          14 :     for (auto i = aObjects.rbegin(); i != aObjects.rend(); ++i)
     279          13 :         (*i)->disposeAndClear();
     280             : 
     281          14 :     for (auto i = aObjects.begin(); i != aObjects.end(); ++i)
     282          13 :         (*i)->assertDeleted();
     283             : 
     284          14 :     for (auto i = aObjects.begin(); i != aObjects.end(); ++i)
     285          14 :         delete *i;
     286           1 : }
     287             : 
     288           1 : CPPUNIT_TEST_SUITE_REGISTRATION(LifecycleTest);
     289             : 
     290           4 : CPPUNIT_PLUGIN_IMPLEMENT();
     291             : 
     292             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11