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 | * This file incorporates work covered by the following license notice: |
10 | * |
11 | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | * contributor license agreements. See the NOTICE file distributed |
13 | * with this work for additional information regarding copyright |
14 | * ownership. The ASF licenses this file to you under the Apache |
15 | * License, Version 2.0 (the "License"); you may not use this file |
16 | * except in compliance with the License. You may obtain a copy of |
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | */ |
19 | |
20 | #include <sal/types.h> |
21 | #include "boost/noncopyable.hpp" |
22 | #include "com/sun/star/awt/AsyncCallback.hpp" |
23 | #include "com/sun/star/awt/XCallback.hpp" |
24 | #include "com/sun/star/beans/PropertyState.hpp" |
25 | #include "com/sun/star/beans/PropertyValue.hpp" |
26 | #include "com/sun/star/document/MacroExecMode.hpp" |
27 | #include "com/sun/star/frame/Desktop.hpp" |
28 | #include "com/sun/star/frame/DispatchResultEvent.hpp" |
29 | #include "com/sun/star/frame/DispatchResultState.hpp" |
30 | #include "com/sun/star/frame/XComponentLoader.hpp" |
31 | #include "com/sun/star/frame/XController.hpp" |
32 | #include "com/sun/star/frame/XDispatchProvider.hpp" |
33 | #include "com/sun/star/frame/XDispatchResultListener.hpp" |
34 | #include "com/sun/star/frame/XModel.hpp" |
35 | #include "com/sun/star/frame/XNotifyingDispatch.hpp" |
36 | #include "com/sun/star/lang/EventObject.hpp" |
37 | #include "com/sun/star/uno/Any.hxx" |
38 | #include "com/sun/star/uno/Reference.hxx" |
39 | #include "com/sun/star/uno/RuntimeException.hpp" |
40 | #include "com/sun/star/uno/Sequence.hxx" |
41 | #include "com/sun/star/util/URL.hpp" |
42 | #include "cppuhelper/implbase1.hxx" |
43 | #include "cppunit/TestAssert.h" |
44 | #include "cppunit/TestFixture.h" |
45 | #include "cppunit/extensions/HelperMacros.h" |
46 | #include "cppunit/plugin/TestPlugIn.h" |
47 | #include "osl/conditn.hxx" |
48 | #include "osl/diagnose.h" |
49 | #include "osl/time.h" |
50 | #include "rtl/ustring.h" |
51 | #include "rtl/ustring.hxx" |
52 | #include "unotest/gettestargument.hxx" |
53 | #include "unotest/officeconnection.hxx" |
54 | #include "unotest/toabsolutefileurl.hxx" |
55 | |
56 | namespace { |
57 | |
58 | struct Result: private boost::noncopyable { |
59 | osl::Condition condition; |
60 | bool success; |
61 | OUString result; |
62 | }; |
63 | |
64 | class Listener: |
65 | public cppu::WeakImplHelper1< css::frame::XDispatchResultListener > |
66 | { |
67 | public: |
68 | Listener(Result * result): result_(result) { OSL_ASSERT(result != 0); } |
69 | |
70 | private: |
71 | virtual void SAL_CALL disposing(css::lang::EventObject const &) |
72 | throw (css::uno::RuntimeException) {} |
73 | |
74 | virtual void SAL_CALL dispatchFinished( |
75 | css::frame::DispatchResultEvent const & Result) |
76 | throw (css::uno::RuntimeException); |
77 | |
78 | Result * result_; |
79 | }; |
80 | |
81 | void Listener::dispatchFinished(css::frame::DispatchResultEvent const & Result) |
82 | throw (css::uno::RuntimeException) |
83 | { |
84 | result_->success = |
85 | (Result.State == css::frame::DispatchResultState::SUCCESS) && |
86 | (Result.Result >>= result_->result); |
87 | result_->condition.set(); |
88 | } |
89 | |
90 | class Callback: public cppu::WeakImplHelper1< css::awt::XCallback > { |
91 | public: |
92 | Callback( |
93 | css::uno::Reference< css::frame::XNotifyingDispatch > const & dispatch, |
94 | css::util::URL const & url, |
95 | css::uno::Sequence< css::beans::PropertyValue > const & arguments, |
96 | css::uno::Reference< css::frame::XDispatchResultListener > const & |
97 | listener): |
98 | dispatch_(dispatch), url_(url), arguments_(arguments), |
99 | listener_(listener) |
100 | { OSL_ASSERT(dispatch.is()); } |
101 | |
102 | private: |
103 | virtual void SAL_CALL notify(css::uno::Any const &) |
104 | throw (css::uno::RuntimeException) |
105 | { dispatch_->dispatchWithNotification(url_, arguments_, listener_); } |
106 | |
107 | css::uno::Reference< css::frame::XNotifyingDispatch > dispatch_; |
108 | css::util::URL url_; |
109 | css::uno::Sequence< css::beans::PropertyValue > arguments_; |
110 | css::uno::Reference< css::frame::XDispatchResultListener > listener_; |
111 | }; |
112 | |
113 | class Test: public CppUnit::TestFixture { |
114 | public: |
115 | virtual void setUp(); |
116 | |
117 | virtual void tearDown(); |
118 | |
119 | private: |
120 | CPPUNIT_TEST_SUITE(Test); |
121 | CPPUNIT_TEST(test); |
122 | CPPUNIT_TEST_SUITE_END(); |
123 | |
124 | void test(); |
125 | |
126 | test::OfficeConnection connection_; |
127 | }; |
128 | |
129 | void Test::setUp() { |
130 | connection_.setUp(); |
131 | } |
132 | |
133 | void Test::tearDown() { |
134 | connection_.tearDown(); |
135 | } |
136 | |
137 | void Test::test() { |
138 | OUString doc; |
139 | CPPUNIT_ASSERT( |
140 | test::getTestArgument( |
141 | OUString("smoketest.doc" ), &doc)); |
142 | css::uno::Sequence< css::beans::PropertyValue > args(2); |
143 | args[0].Name = "MacroExecutionMode" ; |
144 | args[0].Handle = -1; |
145 | args[0].Value <<= |
146 | com::sun::star::document::MacroExecMode::ALWAYS_EXECUTE_NO_WARN; |
147 | args[0].State = css::beans::PropertyState_DIRECT_VALUE; |
148 | args[1].Name = "ReadOnly" ; |
149 | args[1].Handle = -1; |
150 | args[1].Value <<= sal_True; |
151 | args[1].State = css::beans::PropertyState_DIRECT_VALUE; |
152 | css::util::URL url; |
153 | url.Complete = "vnd.sun.star.script:Standard.Global.StartTestWithDefaultOptions?" |
154 | "language=Basic&location=document" ; |
155 | |
156 | css::uno::Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create(connection_.getComponentContext()); |
157 | |
158 | css::uno::Reference< css::frame::XNotifyingDispatch > disp( |
159 | css::uno::Reference< css::frame::XDispatchProvider >( |
160 | css::uno::Reference< css::frame::XController >( |
161 | css::uno::Reference< css::frame::XModel >( |
162 | xDesktop->loadComponentFromURL( |
163 | test::toAbsoluteFileUrl(doc), |
164 | OUString("_default" ), |
165 | 0, args), |
166 | css::uno::UNO_QUERY_THROW)->getCurrentController(), |
167 | css::uno::UNO_SET_THROW)->getFrame(), |
168 | css::uno::UNO_QUERY_THROW)->queryDispatch( |
169 | url, OUString("_self" ), 0), |
170 | css::uno::UNO_QUERY_THROW); |
171 | Result result; |
172 | // Shifted to main thread to work around potential deadlocks (i112867): |
173 | com::sun::star::awt::AsyncCallback::create( |
174 | connection_.getComponentContext())->addCallback( |
175 | new Callback( |
176 | disp, url, css::uno::Sequence< css::beans::PropertyValue >(), |
177 | new Listener(&result)), |
178 | css::uno::Any()); |
179 | // Wait for result.condition or connection_ going stale: |
180 | for (;;) { |
181 | TimeValue delay = { 1, 0 }; // 1 sec |
182 | osl::Condition::Result res = result.condition.wait(&delay); |
183 | if (res == osl::Condition::result_ok) { |
184 | break; |
185 | } |
186 | CPPUNIT_ASSERT_EQUAL(osl::Condition::result_timeout, res); |
187 | CPPUNIT_ASSERT(connection_.isStillAlive()); |
188 | } |
189 | CPPUNIT_ASSERT(result.success); |
190 | CPPUNIT_ASSERT_EQUAL(OUString(), result.result); |
191 | } |
192 | |
193 | CPPUNIT_TEST_SUITE_REGISTRATION(Test); |
194 | |
195 | } |
196 | |
197 | CPPUNIT_PLUGIN_IMPLEMENT(); |
198 | |
199 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
200 | |