Make CppunitTest_services instantiate even more services
Change-Id: Id9bfb3886e4a9cbc15a7bf7ef3aefa73bd160e3b
This commit is contained in:
parent
5d8dc045f1
commit
f7cd7b2ce4
@ -494,7 +494,6 @@ certain functionality.
|
|||||||
@li @c jvmaccess
|
@li @c jvmaccess
|
||||||
@li @c linguistic
|
@li @c linguistic
|
||||||
@li @c mysqlc
|
@li @c mysqlc
|
||||||
@li @c postprocess.cppunit
|
|
||||||
@li @c registry
|
@li @c registry
|
||||||
@li @c reportdesign
|
@li @c reportdesign
|
||||||
@li @c rsc
|
@li @c rsc
|
||||||
|
@ -19,6 +19,7 @@ $(eval $(call gb_CppunitTest_use_externals,services, \
|
|||||||
|
|
||||||
$(eval $(call gb_CppunitTest_use_libraries,services, \
|
$(eval $(call gb_CppunitTest_use_libraries,services, \
|
||||||
cppu \
|
cppu \
|
||||||
|
cppuhelper \
|
||||||
sal \
|
sal \
|
||||||
test \
|
test \
|
||||||
vcl \
|
vcl \
|
||||||
@ -26,6 +27,7 @@ $(eval $(call gb_CppunitTest_use_libraries,services, \
|
|||||||
))
|
))
|
||||||
|
|
||||||
$(eval $(call gb_CppunitTest_use_sdk_api,services))
|
$(eval $(call gb_CppunitTest_use_sdk_api,services))
|
||||||
|
$(eval $(call gb_CppunitTest_use_api,services,oovbaapi))
|
||||||
|
|
||||||
$(eval $(call gb_CppunitTest_use_ure,services))
|
$(eval $(call gb_CppunitTest_use_ure,services))
|
||||||
$(eval $(call gb_CppunitTest_use_vcl,services))
|
$(eval $(call gb_CppunitTest_use_vcl,services))
|
||||||
|
@ -7,42 +7,61 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Try to instantiate as many implementations as possible. Finds all
|
||||||
|
// implementations reachable via the service manager. If a given implementation
|
||||||
|
// is the only implementor of some service that has a zero-parameter
|
||||||
|
// constructor, instantiate the implementation through that service name. If a
|
||||||
|
// given implementation does not offer any such contructors (because it does not
|
||||||
|
// support any single-interface--based service, or because for each relevant
|
||||||
|
// service there are multiple implementations or it does not have an appropriate
|
||||||
|
// constructor) but does support at least one accumulation-based service, then
|
||||||
|
// instantiate it through its implementation name (a heuristic to identify
|
||||||
|
// instantiatable implementations that appears to work well).
|
||||||
|
|
||||||
#include <sal/config.h>
|
#include <sal/config.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <com/sun/star/container/XContentEnumerationAccess.hpp>
|
||||||
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
|
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
|
||||||
#include <com/sun/star/lang/XComponent.hpp>
|
#include <com/sun/star/lang/XComponent.hpp>
|
||||||
|
#include <com/sun/star/lang/XServiceInfo.hpp>
|
||||||
#include <com/sun/star/reflection/XServiceConstructorDescription.hpp>
|
#include <com/sun/star/reflection/XServiceConstructorDescription.hpp>
|
||||||
#include <com/sun/star/reflection/XServiceTypeDescription2.hpp>
|
#include <com/sun/star/reflection/XServiceTypeDescription2.hpp>
|
||||||
|
#include <cppuhelper/exc_hlp.hxx>
|
||||||
#include <test/bootstrapfixture.hxx>
|
#include <test/bootstrapfixture.hxx>
|
||||||
#include <vcl/svapp.hxx>
|
#include <vcl/svapp.hxx>
|
||||||
|
|
||||||
using namespace css::container;
|
|
||||||
using namespace css::reflection;
|
|
||||||
using namespace css::uno;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class ServicesTest: public test::BootstrapFixture
|
OString msg(OUString const & string) {
|
||||||
{
|
return OUStringToOString(string, osl_getThreadTextEncoding());
|
||||||
|
}
|
||||||
|
|
||||||
|
class Test: public test::BootstrapFixture {
|
||||||
public:
|
public:
|
||||||
void test();
|
void test();
|
||||||
|
|
||||||
CPPUNIT_TEST_SUITE(ServicesTest);
|
CPPUNIT_TEST_SUITE(Test);
|
||||||
CPPUNIT_TEST(test);
|
CPPUNIT_TEST(test);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createInstance(
|
||||||
|
OUString const & name, bool withArguments,
|
||||||
|
std::vector<css::uno::Reference<css::lang::XComponent>> * components);
|
||||||
};
|
};
|
||||||
|
|
||||||
void ServicesTest::test()
|
void Test::test() {
|
||||||
{
|
// On Windows, blacklist the com.sun.star.comp.report.OReportDefinition
|
||||||
std::vector<OUString> blacklist;
|
// implementation (reportdesign::OReportDefinition in
|
||||||
|
// reportdesign/source/core/api/ReportDefinition.cxx), as it spawns a thread
|
||||||
// On Windows, blacklist the com.sun.star.report.ReportDefinition service,
|
// that forever blocks in SendMessageW when no VCL event loop is running
|
||||||
// as its reportdesign::OReportDefinition implementation (in
|
|
||||||
// reportdesign/source/core/api/ReportDefinition.cxx) spawns a thread that
|
|
||||||
// forever blocks in SendMessageW when no VCL event loop is running
|
|
||||||
// (reportdesign::<anon>::FactoryLoader::execute ->
|
// (reportdesign::<anon>::FactoryLoader::execute ->
|
||||||
// framework::Desktop::findFrame -> framework::TaskCreator::createTask ->
|
// framework::Desktop::findFrame -> framework::TaskCreator::createTask ->
|
||||||
// <anon>::TaskCreatorService::createInstanceWithArguments ->
|
// <anon>::TaskCreatorService::createInstanceWithArguments ->
|
||||||
@ -53,76 +72,174 @@ void ServicesTest::test()
|
|||||||
// WorkWindow::ImplInit -> ImplBorderWindow::ImplBorderWindow ->
|
// WorkWindow::ImplInit -> ImplBorderWindow::ImplBorderWindow ->
|
||||||
// ImplBorderWindow::ImplInit -> Window::ImplInit ->
|
// ImplBorderWindow::ImplInit -> Window::ImplInit ->
|
||||||
// WinSalInstance::CreateFrame -> ImplSendMessage -> SendMessageW):
|
// WinSalInstance::CreateFrame -> ImplSendMessage -> SendMessageW):
|
||||||
blacklist.push_back("com.sun.star.report.ReportDefinition");
|
std::vector<OUString> blacklist;
|
||||||
|
blacklist.push_back("com.sun.star.comp.report.OReportDefinition");
|
||||||
|
|
||||||
Reference< XHierarchicalNameAccess > xTypeManager(
|
//TODO: bug ID
|
||||||
m_xContext->getValueByName(
|
blacklist.push_back("SwXMailMerge");
|
||||||
"/singletons/com.sun.star.reflection.theTypeDescriptionManager"),
|
|
||||||
UNO_QUERY_THROW );
|
css::uno::Reference<css::container::XContentEnumerationAccess> enumAcc(
|
||||||
Sequence<OUString> s = m_xContext->getServiceManager()->getAvailableServiceNames();
|
m_xContext->getServiceManager(), css::uno::UNO_QUERY_THROW);
|
||||||
std::vector< css::uno::Reference<css::lang::XComponent> > comps;
|
css::uno::Reference<css::container::XHierarchicalNameAccess> typeMgr(
|
||||||
for (sal_Int32 i = 0; i < s.getLength(); i++)
|
m_xContext->getValueByName(
|
||||||
{
|
"/singletons/com.sun.star.reflection.theTypeDescriptionManager"),
|
||||||
if (std::find(blacklist.begin(), blacklist.end(), s[i])
|
css::uno::UNO_QUERY_THROW);
|
||||||
!= blacklist.end())
|
css::uno::Sequence<OUString> serviceNames(
|
||||||
{
|
m_xContext->getServiceManager()->getAvailableServiceNames());
|
||||||
continue;
|
struct Constructor {
|
||||||
|
Constructor(
|
||||||
|
OUString const & theServiceName, bool theDefaultConstructor):
|
||||||
|
serviceName(theServiceName),
|
||||||
|
defaultConstructor(theDefaultConstructor)
|
||||||
|
{}
|
||||||
|
OUString serviceName;
|
||||||
|
bool defaultConstructor;
|
||||||
|
};
|
||||||
|
struct Implementation {
|
||||||
|
Implementation(css::uno::Reference<css::lang::XServiceInfo> theFactory):
|
||||||
|
factory(theFactory), accumulationBased(false) {}
|
||||||
|
css::uno::Reference<css::lang::XServiceInfo> factory;
|
||||||
|
std::vector<Constructor> constructors;
|
||||||
|
bool accumulationBased;
|
||||||
|
};
|
||||||
|
std::map<OUString, Implementation> impls;
|
||||||
|
for (sal_Int32 i = 0; i != serviceNames.getLength(); ++i) {
|
||||||
|
css::uno::Reference<css::container::XEnumeration> serviceImpls1(
|
||||||
|
enumAcc->createContentEnumeration(serviceNames[i]),
|
||||||
|
css::uno::UNO_SET_THROW);
|
||||||
|
std::vector<css::uno::Reference<css::lang::XServiceInfo>> serviceImpls2;
|
||||||
|
while (serviceImpls1->hasMoreElements()) {
|
||||||
|
serviceImpls2.push_back(
|
||||||
|
css::uno::Reference<css::lang::XServiceInfo>(
|
||||||
|
serviceImpls1->nextElement(), css::uno::UNO_QUERY_THROW));
|
||||||
}
|
}
|
||||||
if (!xTypeManager->hasByHierarchicalName(s[i]))
|
css::uno::Reference<css::reflection::XServiceTypeDescription2> desc;
|
||||||
{
|
if (typeMgr->hasByHierarchicalName(serviceNames[i])) {
|
||||||
SAL_WARN(
|
desc.set(
|
||||||
"postprocess.cppunit",
|
typeMgr->getByHierarchicalName(serviceNames[i]),
|
||||||
"fantasy service name \"" << s[i] << "\"");
|
css::uno::UNO_QUERY_THROW);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
SAL_WARN(
|
if (serviceImpls2.empty()) {
|
||||||
"postprocess.cppunit",
|
if (desc.is()) {
|
||||||
"trying (index: " << i << ") \"" << s[i] << "\"");
|
CPPUNIT_ASSERT_MESSAGE(
|
||||||
Reference< XServiceTypeDescription2 > xDesc(
|
(OString(
|
||||||
xTypeManager->getByHierarchicalName(s[i]), UNO_QUERY_THROW);
|
"no implementations of singlie-interface--based \""
|
||||||
Sequence< Reference< XServiceConstructorDescription > > xseq = xDesc->getConstructors();
|
+ msg(serviceNames[i]) + "\"")
|
||||||
SAL_WARN_IF(xseq.getLength() == 0, "postprocess.cppunit", "not tested because there is no constructor");
|
.getStr()),
|
||||||
for (sal_Int32 c = 0; c < xseq.getLength(); c++)
|
!desc->isSingleInterfaceBased());
|
||||||
if (!xseq[c]->getParameters().hasElements())
|
std::cout
|
||||||
{
|
<< "accumulation-based service \"" << serviceNames[i]
|
||||||
Reference< XInterface > instance;
|
<< "\" without implementations\n";
|
||||||
try
|
} else {
|
||||||
{
|
std::cout
|
||||||
OString message = OUStringToOString(s[i], RTL_TEXTENCODING_UTF8);
|
<< "fantasy service name \"" << serviceNames[i]
|
||||||
bool bDefConstructor = xseq[c]->isDefaultConstructor();
|
<< "\" without implementations\n";
|
||||||
Reference< css::lang::XMultiComponentFactory > serviceManager = m_xContext->getServiceManager();
|
}
|
||||||
|
} else {
|
||||||
if( bDefConstructor )
|
for (auto const & j: serviceImpls2) {
|
||||||
instance = serviceManager->createInstanceWithContext(s[i], m_xContext);
|
OUString name(j->getImplementationName());
|
||||||
else
|
auto k = impls.find(name);
|
||||||
instance = serviceManager->createInstanceWithArgumentsAndContext(
|
if (k == impls.end()) {
|
||||||
s[i], css::uno::Sequence<css::uno::Any>(), m_xContext);
|
k = impls.insert(std::make_pair(name, Implementation(j)))
|
||||||
|
.first;
|
||||||
CPPUNIT_ASSERT_MESSAGE( message.getStr(), instance.is() );
|
} else {
|
||||||
|
CPPUNIT_ASSERT_MESSAGE(
|
||||||
|
(OString(
|
||||||
|
"multiple implementations named \"" + msg(name)
|
||||||
|
+ "\"")
|
||||||
|
.getStr()),
|
||||||
|
j == k->second.factory);
|
||||||
}
|
}
|
||||||
catch(const Exception & e)
|
if (desc.is()) {
|
||||||
{
|
if (desc->isSingleInterfaceBased()) {
|
||||||
OString exc = "Exception thrown while creating " +
|
if (serviceImpls2.size() == 1) {
|
||||||
OUStringToOString(s[i] + ": " + e.Message, RTL_TEXTENCODING_UTF8);
|
css::uno::Sequence<
|
||||||
CPPUNIT_FAIL(exc.getStr());
|
css::uno::Reference<
|
||||||
}
|
css::reflection::XServiceConstructorDescription>>
|
||||||
css::uno::Reference<css::lang::XComponent> comp(
|
ctors(desc->getConstructors());
|
||||||
instance, css::uno::UNO_QUERY);
|
for (sal_Int32 l = 0; l != ctors.getLength(); ++l) {
|
||||||
if (comp.is()) {
|
if (!ctors[l]->getParameters().hasElements()) {
|
||||||
comps.push_back(comp);
|
k->second.constructors.push_back(
|
||||||
|
Constructor(
|
||||||
|
serviceNames[i],
|
||||||
|
ctors[l]->isDefaultConstructor()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
k->second.accumulationBased = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout
|
||||||
|
<< "implementation \"" << name
|
||||||
|
<< "\" supports fantasy service name \""
|
||||||
|
<< serviceNames[i] << "\"\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::vector<css::uno::Reference<css::lang::XComponent>> comps;
|
||||||
|
for (auto const & i: impls) {
|
||||||
|
if (std::find(blacklist.begin(), blacklist.end(), i.first)
|
||||||
|
== blacklist.end())
|
||||||
|
{
|
||||||
|
if (i.second.constructors.empty()) {
|
||||||
|
if (i.second.accumulationBased) {
|
||||||
|
createInstance(i.first, false, &comps);
|
||||||
|
} else {
|
||||||
|
std::cout
|
||||||
|
<< "no obvious way to instantiate implementation \""
|
||||||
|
<< i.first << "\"\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (auto const & j: i.second.constructors) {
|
||||||
|
createInstance(
|
||||||
|
j.serviceName, !j.defaultConstructor, &comps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SolarMutexReleaser rel;
|
SolarMutexReleaser rel;
|
||||||
for (std::vector< css::uno::Reference<css::lang::XComponent> >::iterator i(
|
for (auto const & i: comps) {
|
||||||
comps.begin());
|
i->dispose();
|
||||||
i != comps.end(); ++i)
|
|
||||||
{
|
|
||||||
(*i)->dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CPPUNIT_TEST_SUITE_REGISTRATION(ServicesTest);
|
void Test::createInstance(
|
||||||
|
OUString const & name, bool withArguments,
|
||||||
|
std::vector<css::uno::Reference<css::lang::XComponent>> * components)
|
||||||
|
{
|
||||||
|
assert(components != nullptr);
|
||||||
|
css::uno::Reference<css::uno::XInterface> inst;
|
||||||
|
try {
|
||||||
|
if (withArguments) {
|
||||||
|
inst = m_xContext->getServiceManager()
|
||||||
|
->createInstanceWithArgumentsAndContext(
|
||||||
|
name, css::uno::Sequence<css::uno::Any>(), m_xContext);
|
||||||
|
} else {
|
||||||
|
inst = m_xContext->getServiceManager()->createInstanceWithContext(
|
||||||
|
name, m_xContext);
|
||||||
|
}
|
||||||
|
} catch (css::uno::Exception & e) {
|
||||||
|
css::uno::Any a(cppu::getCaughtException());
|
||||||
|
CPPUNIT_FAIL(
|
||||||
|
OString(
|
||||||
|
"creating \"" + msg(name) + "\" caused "
|
||||||
|
+ msg(a.getValueTypeName()) + " \"" + msg(e.Message) + "\"")
|
||||||
|
.getStr());
|
||||||
|
}
|
||||||
|
CPPUNIT_ASSERT_MESSAGE(
|
||||||
|
(OString("creating \"" + msg(name) + "\" returned null reference")
|
||||||
|
.getStr()),
|
||||||
|
inst.is());
|
||||||
|
css::uno::Reference<css::lang::XComponent> comp(inst, css::uno::UNO_QUERY);
|
||||||
|
if (comp.is()) {
|
||||||
|
components->push_back(comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user