Update git submodules
[LibreOffice.git] / vcl / qa / cppunit / lifecycle.cxx
blobeaeed28b9b979e0002689f7088a749331fdca411
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/XVclWindowPeer.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 testLeakage();
41 void testToolkit();
43 CPPUNIT_TEST_SUITE(LifecycleTest);
44 CPPUNIT_TEST(testCast);
45 CPPUNIT_TEST(testVirtualDevice);
46 CPPUNIT_TEST(testMultiDispose);
47 CPPUNIT_TEST(testIsolatedWidgets);
48 CPPUNIT_TEST(testParentedWidgets);
49 CPPUNIT_TEST(testChildDispose);
50 CPPUNIT_TEST(testPostDispose);
51 CPPUNIT_TEST(testLeakage);
52 CPPUNIT_TEST(testToolkit);
53 CPPUNIT_TEST_SUITE_END();
56 // A compile time sanity check
57 void LifecycleTest::testCast()
59 ScopedVclPtrInstance< PushButton > xButton( nullptr, 0 );
60 ScopedVclPtr<vcl::Window> xWindow(xButton);
62 ScopedVclPtrInstance< MetricField > xField( nullptr, 0 );
63 ScopedVclPtr<SpinField> xSpin(xField);
64 ScopedVclPtr<Edit> xEdit(xField);
66 // the following line should NOT compile
67 // VclPtr<PushButton> xButton2(xWindow);
70 void LifecycleTest::testVirtualDevice()
72 VclPtr<VirtualDevice> pVDev = VclPtr< VirtualDevice >::Create();
73 ScopedVclPtrInstance< VirtualDevice > pVDev2;
74 VclPtrInstance<VirtualDevice> pVDev3;
75 VclPtrInstance<VirtualDevice> pVDev4(DeviceFormat::WITHOUT_ALPHA);
76 CPPUNIT_ASSERT(!!pVDev);
77 CPPUNIT_ASSERT(!!pVDev2);
78 CPPUNIT_ASSERT(!!pVDev3);
79 CPPUNIT_ASSERT(!!pVDev4);
80 pVDev.disposeAndClear();
81 pVDev4.disposeAndClear();
84 void LifecycleTest::testMultiDispose()
86 VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
87 CPPUNIT_ASSERT(xWin);
88 xWin->disposeOnce();
89 xWin->disposeOnce();
90 xWin->disposeOnce();
91 CPPUNIT_ASSERT(!xWin->GetWindow(GetWindowType::Parent));
92 CPPUNIT_ASSERT(!xWin->GetChild(0));
93 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(0), xWin->GetChildCount());
96 void LifecycleTest::testWidgets(vcl::Window *pParent)
99 ScopedVclPtrInstance< PushButton > aPtr( pParent );
100 (void)aPtr; // silence unused variable warning
103 ScopedVclPtrInstance< OKButton > aPtr( pParent );
104 (void)aPtr; // silence unused variable warning
107 ScopedVclPtrInstance< CancelButton > aPtr( pParent );
108 (void)aPtr; // silence unused variable warning
111 ScopedVclPtrInstance< HelpButton > aPtr( pParent );
112 (void)aPtr; // silence unused variable warning
115 // Some widgets really insist on adoption.
116 if (pParent)
119 ScopedVclPtrInstance< CheckBox > aPtr( pParent );
120 (void)aPtr; // silence unused variable warning
123 ScopedVclPtrInstance< Edit > aPtr( pParent );
124 (void)aPtr; // silence unused variable warning
127 ScopedVclPtrInstance< ComboBox > aPtr( pParent );
128 (void)aPtr; // silence unused variable warning
131 ScopedVclPtrInstance< RadioButton > aPtr( pParent, true, 0 );
132 (void)aPtr; // silence unused variable warning
137 void LifecycleTest::testIsolatedWidgets()
139 testWidgets(nullptr);
142 void LifecycleTest::testParentedWidgets()
144 ScopedVclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
145 CPPUNIT_ASSERT(xWin);
146 xWin->Show();
147 testWidgets(xWin);
150 namespace {
152 class DisposableChild : public vcl::Window
154 public:
155 explicit DisposableChild(vcl::Window *pParent) : vcl::Window(pParent) {}
156 virtual ~DisposableChild() override
158 disposeOnce();
164 void LifecycleTest::testChildDispose()
166 VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
167 CPPUNIT_ASSERT(xWin);
168 VclPtrInstance< DisposableChild > xChild( xWin.get() );
169 xWin->Show();
170 xChild->disposeOnce();
171 xWin->disposeOnce();
174 void LifecycleTest::testPostDispose()
176 VclPtrInstance<WorkWindow> xWin(nullptr, WB_APP|WB_STDWORK);
177 xWin->disposeOnce();
179 // check selected methods continue to work post-dispose
180 CPPUNIT_ASSERT(!xWin->GetParent());
181 xWin->Show();
182 CPPUNIT_ASSERT(!xWin->IsReallyShown());
183 CPPUNIT_ASSERT(!xWin->IsEnabled());
184 CPPUNIT_ASSERT(!xWin->IsInputEnabled());
185 CPPUNIT_ASSERT(!xWin->GetChild(0));
186 CPPUNIT_ASSERT(!xWin->GetWindow(GetWindowType::Parent));
189 namespace {
191 template <class vcl_type>
192 class LeakTestClass : public vcl_type
194 bool &mrDeleted;
195 public:
196 template<typename... Arg>
197 LeakTestClass(bool &bDeleted, Arg &&... arg) :
198 vcl_type(std::forward<Arg>(arg)...),
199 mrDeleted(bDeleted)
201 mrDeleted = false;
203 ~LeakTestClass()
205 mrDeleted = true;
209 class LeakTestObject
211 bool mbDeleted;
212 VclPtr<vcl::Window> mxRef;
213 void *mpRef;
214 LeakTestObject()
215 : mbDeleted(false)
216 , mpRef(nullptr)
219 public:
220 template<typename vcl_type, typename... Arg> static LeakTestObject *
221 Create(Arg &&... arg)
223 LeakTestObject *pNew = new LeakTestObject();
224 pNew->mxRef = VclPtr< LeakTestClass< vcl_type > >::Create( pNew->mbDeleted,
225 std::forward<Arg>(arg)...);
226 pNew->mpRef = static_cast<void *>(static_cast<vcl::Window *>(pNew->mxRef));
227 return pNew;
229 const VclPtr<vcl::Window>& getRef() const { return mxRef; }
230 void disposeAndClear()
232 mxRef.disposeAndClear();
234 void assertDeleted()
236 if (!mbDeleted)
238 OUStringBuffer aMsg = "Type '";
239 vcl::Window *pWin = static_cast<vcl::Window *>(mpRef);
240 aMsg.appendAscii(typeid(*pWin).name());
241 aMsg.append("' not freed after dispose");
242 CPPUNIT_FAIL(OUStringToOString(aMsg.makeStringAndClear(),
243 RTL_TEXTENCODING_UTF8).getStr());
250 void LifecycleTest::testLeakage()
252 std::vector<LeakTestObject *> aObjects;
254 // Create objects
255 aObjects.push_back(LeakTestObject::Create<WorkWindow>(nullptr, WB_APP|WB_STDWORK));
256 VclPtr<vcl::Window> xParent = aObjects.back()->getRef();
258 aObjects.push_back(LeakTestObject::Create<PushButton>(xParent));
259 aObjects.push_back(LeakTestObject::Create<CheckBox>(xParent));
260 aObjects.push_back(LeakTestObject::Create<Edit>(xParent));
261 aObjects.push_back(LeakTestObject::Create<ComboBox>(xParent));
262 aObjects.push_back(LeakTestObject::Create<RadioButton>(xParent, true, 0));
264 { // something that looks like a dialog
265 aObjects.push_back(LeakTestObject::Create<Dialog>(xParent,WB_CLIPCHILDREN|WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE|WB_SIZEABLE));
266 VclPtr<vcl::Window> xDlgParent = aObjects.back()->getRef();
267 aObjects.push_back(LeakTestObject::Create<VclVBox>(xDlgParent));
268 VclPtr<vcl::Window> xVBox = aObjects.back()->getRef();
269 aObjects.push_back(LeakTestObject::Create<VclVButtonBox>(xVBox));
272 aObjects.push_back(LeakTestObject::Create<Dialog>(xParent, u"PrintProgressDialog"_ustr, "vcl/ui/printprogressdialog.ui"));
273 xParent.clear();
275 for (auto i = aObjects.rbegin(); i != aObjects.rend(); ++i)
276 (*i)->getRef()->Show();
278 for (auto i = aObjects.rbegin(); i != aObjects.rend(); ++i)
279 (*i)->disposeAndClear();
281 for (auto i = aObjects.begin(); i != aObjects.end(); ++i)
282 (*i)->assertDeleted();
284 for (auto i = aObjects.begin(); i != aObjects.end(); ++i)
285 delete *i;
288 void LifecycleTest::testToolkit()
290 LeakTestObject *pVclWin = LeakTestObject::Create<WorkWindow>(nullptr, WB_APP|WB_STDWORK);
291 css::uno::Reference<css::awt::XWindow> xWindow(pVclWin->getRef()->GetComponentInterface(), css::uno::UNO_QUERY);
292 CPPUNIT_ASSERT(xWindow.is());
294 // test UNO dispose
295 css::uno::Reference<css::lang::XComponent> xWinComponent = xWindow;
296 CPPUNIT_ASSERT(xWinComponent.is());
297 CPPUNIT_ASSERT(!pVclWin->getRef()->isDisposed());
298 xWinComponent->dispose();
299 CPPUNIT_ASSERT(pVclWin->getRef()->isDisposed());
301 // test UNO cleanup
302 xWinComponent.clear();
303 xWindow.clear();
304 pVclWin->disposeAndClear();
305 pVclWin->assertDeleted();
307 delete pVclWin;
310 CPPUNIT_TEST_SUITE_REGISTRATION(LifecycleTest);
312 CPPUNIT_PLUGIN_IMPLEMENT();
314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */