bump product version to 5.0.4.1
[LibreOffice.git] / vcl / qa / cppunit / lifecycle.cxx
bloba4e7e774e653d145d59a0b3fe81462a3438d0c21
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <unotest/filters-test.hxx>
11 #include <test/bootstrapfixture.hxx>
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>
24 class LifecycleTest : public test::BootstrapFixture
26 void testWidgets(vcl::Window *pParent);
28 public:
29 LifecycleTest() : BootstrapFixture(true, false) {}
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();
41 CPPUNIT_TEST_SUITE(LifecycleTest);
42 CPPUNIT_TEST(testCast);
43 CPPUNIT_TEST(testVirtualDevice);
44 CPPUNIT_TEST(testMultiDispose);
45 CPPUNIT_TEST(testIsolatedWidgets);
46 CPPUNIT_TEST(testParentedWidgets);
47 CPPUNIT_TEST(testChildDispose);
48 CPPUNIT_TEST(testPostDispose);
49 CPPUNIT_TEST(testFocus);
50 CPPUNIT_TEST(testLeakage);
51 CPPUNIT_TEST_SUITE_END();
54 // A compile time sanity check
55 void LifecycleTest::testCast()
57 ScopedVclPtrInstance< PushButton > xButton( nullptr, 0 );
58 ScopedVclPtr<vcl::Window> xWindow(xButton);
60 ScopedVclPtrInstance< MetricField > xField( nullptr, 0 );
61 ScopedVclPtr<SpinField> xSpin(xField);
62 ScopedVclPtr<Edit> xEdit(xField);
64 // the following line should NOT compile
65 // VclPtr<PushButton> xButton2(xWindow);
68 void LifecycleTest::testVirtualDevice()
70 VclPtr<VirtualDevice> pVDev = VclPtr< VirtualDevice >::Create();
71 ScopedVclPtrInstance< VirtualDevice > pVDev2;
72 VclPtrInstance<VirtualDevice> pVDev3;
73 VclPtrInstance<VirtualDevice> pVDev4( 1 );
74 CPPUNIT_ASSERT(!!pVDev && !!pVDev2 && !!pVDev3 && !!pVDev4);
77 void LifecycleTest::testMultiDispose()
79 VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
80 CPPUNIT_ASSERT(xWin.get() != NULL);
81 xWin->disposeOnce();
82 xWin->disposeOnce();
83 xWin->disposeOnce();
84 CPPUNIT_ASSERT(xWin->GetWindow(GetWindowType::Parent) == NULL);
85 CPPUNIT_ASSERT(xWin->GetChild(0) == NULL);
86 CPPUNIT_ASSERT(xWin->GetChildCount() == 0);
89 void LifecycleTest::testWidgets(vcl::Window *pParent)
91 { ScopedVclPtrInstance< PushButton > aPtr( pParent ); }
92 { ScopedVclPtrInstance< OKButton > aPtr( pParent ); }
93 { ScopedVclPtrInstance< CancelButton > aPtr( pParent ); }
94 { ScopedVclPtrInstance< HelpButton > aPtr( pParent ); }
96 // Some widgets really insist on adoption.
97 if (pParent)
99 { ScopedVclPtrInstance< CheckBox > aPtr( pParent ); }
100 { ScopedVclPtrInstance< Edit > aPtr( pParent ); }
101 { ScopedVclPtrInstance< ComboBox > aPtr( pParent ); }
102 { ScopedVclPtrInstance< RadioButton > aPtr( pParent ); }
106 void LifecycleTest::testIsolatedWidgets()
108 testWidgets(NULL);
111 void LifecycleTest::testParentedWidgets()
113 ScopedVclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
114 CPPUNIT_ASSERT(xWin.get() != NULL);
115 xWin->Show();
116 testWidgets(xWin);
119 class DisposableChild : public vcl::Window
121 public:
122 DisposableChild(vcl::Window *pParent) : vcl::Window(pParent) {}
123 virtual ~DisposableChild()
125 disposeOnce();
129 void LifecycleTest::testChildDispose()
131 VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
132 CPPUNIT_ASSERT(xWin.get() != NULL);
133 VclPtrInstance< DisposableChild > xChild( xWin.get() );
134 xWin->Show();
135 xChild->disposeOnce();
136 xWin->disposeOnce();
139 void LifecycleTest::testPostDispose()
141 VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
142 xWin->disposeOnce();
144 // check selected methods continue to work post-dispose
145 CPPUNIT_ASSERT(!xWin->GetParent());
146 xWin->Show();
147 CPPUNIT_ASSERT(!xWin->IsReallyShown());
148 CPPUNIT_ASSERT(!xWin->IsEnabled());
149 CPPUNIT_ASSERT(!xWin->IsInputEnabled());
150 CPPUNIT_ASSERT(!xWin->GetChild(0));
151 CPPUNIT_ASSERT(!xWin->GetWindow(GetWindowType::Parent));
154 class FocusCrashPostDispose : public TabControl
156 public:
157 FocusCrashPostDispose(vcl::Window *pParent) :
158 TabControl(pParent, 0)
161 virtual bool PreNotify( NotifyEvent& ) SAL_OVERRIDE
163 return false;
165 virtual bool Notify( NotifyEvent& ) SAL_OVERRIDE
167 // CPPUNIT_FAIL("notify");
168 return false;
170 virtual void GetFocus() SAL_OVERRIDE
172 CPPUNIT_FAIL("get focus");
174 virtual void LoseFocus() SAL_OVERRIDE
176 CPPUNIT_FAIL("this should never be called");
180 void LifecycleTest::testFocus()
182 ScopedVclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
183 ScopedVclPtrInstance< FocusCrashPostDispose > xChild(xWin);
184 xWin->Show();
185 xChild->GrabFocus();
186 // process asynchronous ToTop
187 Scheduler::ProcessTaskScheduling(false);
188 // FIXME: really awful to test focus issues without showing windows.
189 // CPPUNIT_ASSERT(xChild->HasFocus());
192 template <class vcl_type>
193 class LeakTestClass : public vcl_type
195 bool &mrDeleted;
196 public:
197 template<typename... Arg>
198 LeakTestClass(bool &bDeleted, Arg &&... arg) :
199 vcl_type(std::forward<Arg>(arg)...),
200 mrDeleted(bDeleted)
202 mrDeleted = false;
204 ~LeakTestClass()
206 mrDeleted = true;
210 class LeakTestObject
212 bool mbDeleted;
213 VclPtr<vcl::Window> mxRef;
214 void *mpRef;
215 LeakTestObject() {}
216 public:
217 template<typename vcl_type, typename... Arg> static LeakTestObject *
218 Create(Arg &&... arg)
220 LeakTestObject *pNew = new LeakTestObject();
221 pNew->mxRef = VclPtr< LeakTestClass< vcl_type > >::Create( pNew->mbDeleted,
222 std::forward<Arg>(arg)...);
223 pNew->mpRef = static_cast<void *>(static_cast<vcl::Window *>(pNew->mxRef));
224 return pNew;
226 VclPtr<vcl::Window> getRef() { return mxRef; }
227 void disposeAndClear()
229 mxRef.disposeAndClear();
231 void assertDeleted()
233 if (!mbDeleted)
235 OUStringBuffer aMsg = "Type '";
236 vcl::Window *pWin = static_cast<vcl::Window *>(mpRef);
237 aMsg.appendAscii(typeid(*pWin).name());
238 aMsg.append("' not freed after dispose");
239 CPPUNIT_FAIL(OUStringToOString(aMsg.makeStringAndClear(),
240 RTL_TEXTENCODING_UTF8).getStr());
245 void LifecycleTest::testLeakage()
247 std::vector<LeakTestObject *> aObjects;
249 // Create objects
250 aObjects.push_back(LeakTestObject::Create<WorkWindow>(nullptr, WB_APP|WB_STDWORK));
251 VclPtr<vcl::Window> xParent = aObjects.back()->getRef();
253 aObjects.push_back(LeakTestObject::Create<PushButton>(xParent));
254 aObjects.push_back(LeakTestObject::Create<OKButton>(xParent));
255 aObjects.push_back(LeakTestObject::Create<CancelButton>(xParent));
256 aObjects.push_back(LeakTestObject::Create<HelpButton>(xParent));
257 aObjects.push_back(LeakTestObject::Create<CheckBox>(xParent));
258 aObjects.push_back(LeakTestObject::Create<Edit>(xParent));
259 aObjects.push_back(LeakTestObject::Create<ComboBox>(xParent));
260 aObjects.push_back(LeakTestObject::Create<RadioButton>(xParent));
262 { // something that looks like a dialog
263 aObjects.push_back(LeakTestObject::Create<Dialog>(xParent,WB_CLIPCHILDREN|WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE|WB_SIZEABLE));
264 VclPtr<vcl::Window> xDlgParent = aObjects.back()->getRef();
265 aObjects.push_back(LeakTestObject::Create<VclVBox>(xDlgParent));
266 VclPtr<vcl::Window> xVBox = aObjects.back()->getRef();
267 aObjects.push_back(LeakTestObject::Create<VclVButtonBox>(xVBox));
270 #if 0 // FIXME - would be good to get internal paths working.
271 aObjects.push_back(LeakTestObject::Create<ModelessDialog>(xParent, "PrintProgressDialog", "vcl/ui/printprogressdialog.ui"));
272 #endif
273 aObjects.push_back(LeakTestObject::Create<ModalDialog>(xParent));
274 xParent.clear();
276 for (auto i = aObjects.rbegin(); i != aObjects.rend(); ++i)
277 (*i)->getRef()->Show();
279 for (auto i = aObjects.rbegin(); i != aObjects.rend(); ++i)
280 (*i)->disposeAndClear();
282 for (auto i = aObjects.begin(); i != aObjects.end(); ++i)
283 (*i)->assertDeleted();
285 for (auto i = aObjects.begin(); i != aObjects.end(); ++i)
286 delete *i;
289 CPPUNIT_TEST_SUITE_REGISTRATION(LifecycleTest);
291 CPPUNIT_PLUGIN_IMPLEMENT();
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */