nss: upgrade to release 3.73
[LibreOffice.git] / vcl / qa / cppunit / lifecycle.cxx
blob418cecbf237b6b9eaa4446539ee88b39a6eeccbd
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 <test/bootstrapfixture.hxx>
12 #include <vcl/wrkwin.hxx>
13 #include <vcl/toolkit/edit.hxx>
14 #include <vcl/toolkit/button.hxx>
15 #include <vcl/toolkit/combobox.hxx>
16 #include <vcl/toolkit/dialog.hxx>
17 #include <vcl/toolkit/field.hxx>
18 #include <vcl/virdev.hxx>
19 #include <vcl/tabctrl.hxx>
20 #include <vcl/layout.hxx>
21 #include <vcl/scheduler.hxx>
22 #include <com/sun/star/awt/XWindow.hpp>
23 #include <com/sun/star/awt/XWindowPeer.hpp>
24 #include <com/sun/star/lang/XComponent.hpp>
26 class LifecycleTest : public test::BootstrapFixture
28 void testWidgets(vcl::Window *pParent);
30 public:
31 LifecycleTest() : BootstrapFixture(true, false) {}
33 void testCast();
34 void testVirtualDevice();
35 void testMultiDispose();
36 void testIsolatedWidgets();
37 void testParentedWidgets();
38 void testChildDispose();
39 void testPostDispose();
40 void testFocus();
41 void testLeakage();
42 void testToolkit();
44 CPPUNIT_TEST_SUITE(LifecycleTest);
45 CPPUNIT_TEST(testCast);
46 CPPUNIT_TEST(testVirtualDevice);
47 CPPUNIT_TEST(testMultiDispose);
48 CPPUNIT_TEST(testIsolatedWidgets);
49 CPPUNIT_TEST(testParentedWidgets);
50 CPPUNIT_TEST(testChildDispose);
51 CPPUNIT_TEST(testPostDispose);
52 CPPUNIT_TEST(testFocus);
53 CPPUNIT_TEST(testLeakage);
54 CPPUNIT_TEST(testToolkit);
55 CPPUNIT_TEST_SUITE_END();
58 // A compile time sanity check
59 void LifecycleTest::testCast()
61 ScopedVclPtrInstance< PushButton > xButton( nullptr, 0 );
62 ScopedVclPtr<vcl::Window> xWindow(xButton);
64 ScopedVclPtrInstance< MetricField > xField( nullptr, 0 );
65 ScopedVclPtr<SpinField> xSpin(xField);
66 ScopedVclPtr<Edit> xEdit(xField);
68 // the following line should NOT compile
69 // VclPtr<PushButton> xButton2(xWindow);
72 void LifecycleTest::testVirtualDevice()
74 VclPtr<VirtualDevice> pVDev = VclPtr< VirtualDevice >::Create();
75 ScopedVclPtrInstance< VirtualDevice > pVDev2;
76 VclPtrInstance<VirtualDevice> pVDev3;
77 VclPtrInstance<VirtualDevice> pVDev4(DeviceFormat::BITMASK);
78 CPPUNIT_ASSERT(!!pVDev && !!pVDev2 && !!pVDev3 && !!pVDev4);
79 pVDev.disposeAndClear();
80 pVDev4.disposeAndClear();
83 void LifecycleTest::testMultiDispose()
85 VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
86 CPPUNIT_ASSERT(xWin);
87 xWin->disposeOnce();
88 xWin->disposeOnce();
89 xWin->disposeOnce();
90 CPPUNIT_ASSERT(!xWin->GetWindow(GetWindowType::Parent));
91 CPPUNIT_ASSERT(!xWin->GetChild(0));
92 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(0), xWin->GetChildCount());
95 void LifecycleTest::testWidgets(vcl::Window *pParent)
98 ScopedVclPtrInstance< PushButton > aPtr( pParent );
99 (void)aPtr; // silence unused variable warning
102 ScopedVclPtrInstance< OKButton > aPtr( pParent );
103 (void)aPtr; // silence unused variable warning
106 ScopedVclPtrInstance< CancelButton > aPtr( pParent );
107 (void)aPtr; // silence unused variable warning
110 ScopedVclPtrInstance< HelpButton > aPtr( pParent );
111 (void)aPtr; // silence unused variable warning
114 // Some widgets really insist on adoption.
115 if (pParent)
118 ScopedVclPtrInstance< CheckBox > aPtr( pParent );
119 (void)aPtr; // silence unused variable warning
122 ScopedVclPtrInstance< Edit > aPtr( pParent );
123 (void)aPtr; // silence unused variable warning
126 ScopedVclPtrInstance< ComboBox > aPtr( pParent );
127 (void)aPtr; // silence unused variable warning
130 ScopedVclPtrInstance< RadioButton > aPtr( pParent, true, 0 );
131 (void)aPtr; // silence unused variable warning
136 void LifecycleTest::testIsolatedWidgets()
138 testWidgets(nullptr);
141 void LifecycleTest::testParentedWidgets()
143 ScopedVclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
144 CPPUNIT_ASSERT(xWin);
145 xWin->Show();
146 testWidgets(xWin);
149 namespace {
151 class DisposableChild : public vcl::Window
153 public:
154 explicit DisposableChild(vcl::Window *pParent) : vcl::Window(pParent) {}
155 virtual ~DisposableChild() override
157 disposeOnce();
163 void LifecycleTest::testChildDispose()
165 VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
166 CPPUNIT_ASSERT(xWin);
167 VclPtrInstance< DisposableChild > xChild( xWin.get() );
168 xWin->Show();
169 xChild->disposeOnce();
170 xWin->disposeOnce();
173 void LifecycleTest::testPostDispose()
175 VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
176 xWin->disposeOnce();
178 // check selected methods continue to work post-dispose
179 CPPUNIT_ASSERT(!xWin->GetParent());
180 xWin->Show();
181 CPPUNIT_ASSERT(!xWin->IsReallyShown());
182 CPPUNIT_ASSERT(!xWin->IsEnabled());
183 CPPUNIT_ASSERT(!xWin->IsInputEnabled());
184 CPPUNIT_ASSERT(!xWin->GetChild(0));
185 CPPUNIT_ASSERT(!xWin->GetWindow(GetWindowType::Parent));
188 namespace {
190 class FocusCrashPostDispose : public TabControl
192 public:
193 explicit FocusCrashPostDispose(vcl::Window *pParent) :
194 TabControl(pParent, 0)
197 virtual bool PreNotify( NotifyEvent& ) override
199 return false;
201 virtual bool EventNotify( NotifyEvent& ) override
203 return false;
205 virtual void GetFocus() override
207 CPPUNIT_FAIL("get focus");
209 virtual void LoseFocus() override
211 CPPUNIT_FAIL("this should never be called");
217 void LifecycleTest::testFocus()
219 ScopedVclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
220 ScopedVclPtrInstance< FocusCrashPostDispose > xChild(xWin);
221 xWin->Show();
222 xChild->GrabFocus();
223 // process asynchronous ToTop
224 Scheduler::ProcessTaskScheduling();
225 // FIXME: really awful to test focus issues without showing windows.
226 // CPPUNIT_ASSERT(xChild->HasFocus());
229 namespace {
231 template <class vcl_type>
232 class LeakTestClass : public vcl_type
234 bool &mrDeleted;
235 public:
236 template<typename... Arg>
237 LeakTestClass(bool &bDeleted, Arg &&... arg) :
238 vcl_type(std::forward<Arg>(arg)...),
239 mrDeleted(bDeleted)
241 mrDeleted = false;
243 ~LeakTestClass()
245 mrDeleted = true;
249 class LeakTestObject
251 bool mbDeleted;
252 VclPtr<vcl::Window> mxRef;
253 void *mpRef;
254 LeakTestObject()
255 : mbDeleted(false)
256 , mpRef(nullptr)
259 public:
260 template<typename vcl_type, typename... Arg> static LeakTestObject *
261 Create(Arg &&... arg)
263 LeakTestObject *pNew = new LeakTestObject();
264 pNew->mxRef = VclPtr< LeakTestClass< vcl_type > >::Create( pNew->mbDeleted,
265 std::forward<Arg>(arg)...);
266 pNew->mpRef = static_cast<void *>(static_cast<vcl::Window *>(pNew->mxRef));
267 return pNew;
269 const VclPtr<vcl::Window>& getRef() const { return mxRef; }
270 void disposeAndClear()
272 mxRef.disposeAndClear();
274 void assertDeleted()
276 if (!mbDeleted)
278 OUStringBuffer aMsg = "Type '";
279 vcl::Window *pWin = static_cast<vcl::Window *>(mpRef);
280 aMsg.appendAscii(typeid(*pWin).name());
281 aMsg.append("' not freed after dispose");
282 CPPUNIT_FAIL(OUStringToOString(aMsg.makeStringAndClear(),
283 RTL_TEXTENCODING_UTF8).getStr());
290 void LifecycleTest::testLeakage()
292 std::vector<LeakTestObject *> aObjects;
294 // Create objects
295 aObjects.push_back(LeakTestObject::Create<WorkWindow>(nullptr, WB_APP|WB_STDWORK));
296 VclPtr<vcl::Window> xParent = aObjects.back()->getRef();
298 aObjects.push_back(LeakTestObject::Create<PushButton>(xParent));
299 aObjects.push_back(LeakTestObject::Create<CheckBox>(xParent));
300 aObjects.push_back(LeakTestObject::Create<Edit>(xParent));
301 aObjects.push_back(LeakTestObject::Create<ComboBox>(xParent));
302 aObjects.push_back(LeakTestObject::Create<RadioButton>(xParent, true, 0));
304 { // something that looks like a dialog
305 aObjects.push_back(LeakTestObject::Create<Dialog>(xParent,WB_CLIPCHILDREN|WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE|WB_SIZEABLE));
306 VclPtr<vcl::Window> xDlgParent = aObjects.back()->getRef();
307 aObjects.push_back(LeakTestObject::Create<VclVBox>(xDlgParent));
308 VclPtr<vcl::Window> xVBox = aObjects.back()->getRef();
309 aObjects.push_back(LeakTestObject::Create<VclVButtonBox>(xVBox));
312 aObjects.push_back(LeakTestObject::Create<Dialog>(xParent, "PrintProgressDialog", "vcl/ui/printprogressdialog.ui"));
313 xParent.clear();
315 for (auto i = aObjects.rbegin(); i != aObjects.rend(); ++i)
316 (*i)->getRef()->Show();
318 for (auto i = aObjects.rbegin(); i != aObjects.rend(); ++i)
319 (*i)->disposeAndClear();
321 for (auto i = aObjects.begin(); i != aObjects.end(); ++i)
322 (*i)->assertDeleted();
324 for (auto i = aObjects.begin(); i != aObjects.end(); ++i)
325 delete *i;
328 void LifecycleTest::testToolkit()
330 LeakTestObject *pVclWin = LeakTestObject::Create<WorkWindow>(nullptr, WB_APP|WB_STDWORK);
331 css::uno::Reference<css::awt::XWindow> xWindow(pVclWin->getRef()->GetComponentInterface(), css::uno::UNO_QUERY);
332 CPPUNIT_ASSERT(xWindow.is());
334 // test UNO dispose
335 css::uno::Reference<css::lang::XComponent> xWinComponent = xWindow;
336 CPPUNIT_ASSERT(xWinComponent.is());
337 CPPUNIT_ASSERT(!pVclWin->getRef()->IsDisposed());
338 xWinComponent->dispose();
339 CPPUNIT_ASSERT(pVclWin->getRef()->IsDisposed());
341 // test UNO cleanup
342 xWinComponent.clear();
343 xWindow.clear();
344 pVclWin->disposeAndClear();
345 pVclWin->assertDeleted();
347 delete pVclWin;
350 CPPUNIT_TEST_SUITE_REGISTRATION(LifecycleTest);
352 CPPUNIT_PLUGIN_IMPLEMENT();
354 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */