1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <test/unoapi_test.hxx>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/util/URLTransformer.hpp>
#include <comphelper/propertyvalue.hxx>
#include <salhelper/thread.hxx>
#include <vcl/svapp.hxx>
#include <vcl/scheduler.hxx>
#include <vcl/wrkwin.hxx>
using namespace ::com::sun::star;
namespace
{
/// Covers framework/source/services/ fixes.
class Test : public UnoApiTest
{
public:
Test()
: UnoApiTest(u"/framework/qa/cppunit/data/"_ustr)
{
}
};
/// Invokes XFrameImpl::loadComponentFromURL() on a thread.
class TestThread : public salhelper::Thread
{
uno::Reference<frame::XComponentLoader> mxComponentLoader;
uno::Reference<lang::XComponent>& mrComponent;
public:
TestThread(const uno::Reference<frame::XComponentLoader>& xComponentLoader,
uno::Reference<lang::XComponent>& rComponent);
void execute() override;
};
TestThread::TestThread(const uno::Reference<frame::XComponentLoader>& xComponentLoader,
uno::Reference<lang::XComponent>& rComponent)
: salhelper::Thread("TestThread")
, mxComponentLoader(xComponentLoader)
, mrComponent(rComponent)
{
}
void TestThread::execute()
{
sal_Int32 nSearchFlags = frame::FrameSearchFlag::AUTO;
uno::Sequence<beans::PropertyValue> aArguments = {
comphelper::makePropertyValue(u"OnMainThread"_ustr, true),
};
// Note how this is invoking loadComponentFromURL() on a frame, not on the desktop, as usual.
mrComponent = mxComponentLoader->loadComponentFromURL(u"private:factory/swriter"_ustr,
u"_self"_ustr, nSearchFlags, aArguments);
}
CPPUNIT_TEST_FIXTURE(Test, testLoadComponentFromURL)
{
// Without the accompanying fix in place, this test would have failed with:
// thread 1: comphelper::SolarMutex::doRelease end: m_nCount is 1
// thread 2: vcl::SolarThreadExecutor::execute: before SolarMutexReleaser ctor
// thread 2: comphelper::SolarMutex::doRelease start: m_nCount is 1, bUnlockAll is 1
// thread 2: comphelper::SolarMutex::doRelease: failed IsCurrentThread() check, will abort
// Notice how thread 2 attempts to release the solar mutex while thread 1 holds it.
// Create a default window, so by the time the thread would post a user event, it doesn't need
// the solar mutex to process a SendMessageW() call on Windows.
ScopedVclPtrInstance<WorkWindow> xWindow(nullptr, WB_APP | WB_STDWORK);
// Variable is not used, it holds the default window.
(void)xWindow;
rtl::Reference<TestThread> xThread;
{
// Start the thread that will load the component, but hold the solar mutex for now, so we
// can see if it blocks.
SolarMutexGuard guard;
uno::Reference<frame::XFrame> xFrame
= mxDesktop->findFrame(u"_blank"_ustr, /*nSearchFlags=*/0);
uno::Reference<frame::XComponentLoader> xComponentLoader(xFrame, uno::UNO_QUERY);
xThread = new TestThread(xComponentLoader, mxComponent);
xThread->launch();
// If loadComponentFromURL() doesn't lock the solar mutex, the test will abort here.
osl::Thread::wait(std::chrono::seconds(1));
}
{
// Now release the solar mutex, so the thread can post the task on the main loop.
SolarMutexReleaser releaser;
osl::Thread::wait(std::chrono::seconds(1));
}
{
// Spin the main loop.
SolarMutexGuard guard;
Scheduler::ProcessEventsToIdle();
}
{
// Stop the thread.
SolarMutexReleaser releaser;
xThread->join();
}
}
CPPUNIT_TEST_FIXTURE(Test, testURLTransformer_parseSmart)
{
// Without the accompanying fix in place, this test would have failed with
// "www.example.com:" treated as scheme, "/8080/foo/" as path, "bar?q=baz"
// as name, and "F" as fragment.
css::util::URL aURL;
aURL.Complete = "www.example.com:8080/foo/bar?q=baz#F";
css::uno::Reference xParser(css::util::URLTransformer::create(m_xContext));
CPPUNIT_ASSERT(xParser->parseSmart(aURL, u"http:"_ustr));
CPPUNIT_ASSERT_EQUAL(u"http://www.example.com:8080/foo/bar?q=baz#F"_ustr, aURL.Complete);
CPPUNIT_ASSERT_EQUAL(u"http://www.example.com:8080/foo/bar"_ustr, aURL.Main);
CPPUNIT_ASSERT_EQUAL(u"http://"_ustr, aURL.Protocol);
CPPUNIT_ASSERT(aURL.User.isEmpty());
CPPUNIT_ASSERT(aURL.Password.isEmpty());
CPPUNIT_ASSERT_EQUAL(u"www.example.com"_ustr, aURL.Server);
CPPUNIT_ASSERT_EQUAL(sal_Int16(8080), aURL.Port);
CPPUNIT_ASSERT_EQUAL(u"/foo/"_ustr, aURL.Path);
CPPUNIT_ASSERT_EQUAL(u"bar"_ustr, aURL.Name);
CPPUNIT_ASSERT_EQUAL(u"q=baz"_ustr, aURL.Arguments);
CPPUNIT_ASSERT_EQUAL(u"F"_ustr, aURL.Mark);
}
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|