1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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
);
29 LifecycleTest() : BootstrapFixture(true, false) {}
32 void testVirtualDevice();
33 void testMultiDispose();
34 void testIsolatedWidgets();
35 void testParentedWidgets();
36 void testChildDispose();
37 void testPostDispose();
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
);
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.
99 { ScopedVclPtrInstance
< CheckBox
> aPtr( pParent
); }
100 { ScopedVclPtrInstance
< Edit
> aPtr( pParent
); }
101 { ScopedVclPtrInstance
< ComboBox
> aPtr( pParent
); }
102 { ScopedVclPtrInstance
< RadioButton
> aPtr( pParent
); }
106 void LifecycleTest::testIsolatedWidgets()
111 void LifecycleTest::testParentedWidgets()
113 ScopedVclPtrInstance
<WorkWindow
> xWin(nullptr, WB_APP
|WB_STDWORK
);
114 CPPUNIT_ASSERT(xWin
.get() != NULL
);
119 class DisposableChild
: public vcl::Window
122 DisposableChild(vcl::Window
*pParent
) : vcl::Window(pParent
) {}
123 virtual ~DisposableChild()
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() );
135 xChild
->disposeOnce();
139 void LifecycleTest::testPostDispose()
141 VclPtrInstance
<WorkWindow
> xWin(nullptr, WB_APP
|WB_STDWORK
);
144 // check selected methods continue to work post-dispose
145 CPPUNIT_ASSERT(!xWin
->GetParent());
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
157 FocusCrashPostDispose(vcl::Window
*pParent
) :
158 TabControl(pParent
, 0)
161 virtual bool PreNotify( NotifyEvent
& ) SAL_OVERRIDE
165 virtual bool Notify( NotifyEvent
& ) SAL_OVERRIDE
167 // CPPUNIT_FAIL("notify");
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
);
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
197 template<typename
... Arg
>
198 LeakTestClass(bool &bDeleted
, Arg
&&... arg
) :
199 vcl_type(std::forward
<Arg
>(arg
)...),
213 VclPtr
<vcl::Window
> mxRef
;
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
));
226 VclPtr
<vcl::Window
> getRef() { return mxRef
; }
227 void disposeAndClear()
229 mxRef
.disposeAndClear();
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
;
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"));
273 aObjects
.push_back(LeakTestObject::Create
<ModalDialog
>(xParent
));
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
)
289 CPPUNIT_TEST_SUITE_REGISTRATION(LifecycleTest
);
291 CPPUNIT_PLUGIN_IMPLEMENT();
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */