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 <config_validation.h>
12 #include <test/bootstrapfixture.hxx>
13 #include <vcl/errinf.hxx>
14 #include <sal/log.hxx>
15 #include <comphelper/processfactory.hxx>
17 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
18 #include <com/sun/star/ucb/XContentProvider.hpp>
19 #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
21 #include <vcl/outdev.hxx>
22 #include <vcl/svapp.hxx>
23 #include <tools/link.hxx>
24 #include <vcl/graphicfilter.hxx>
25 #include <osl/file.hxx>
26 #include <osl/process.h>
27 #include <unotest/getargument.hxx>
28 #include <unotools/tempfile.hxx>
29 #include <vcl/salgtype.hxx>
30 #include <vcl/scheduler.hxx>
31 #include <vcl/virdev.hxx>
32 #include <o3tl/string_view.hxx>
37 #include "setupvcl.hxx"
39 using namespace ::com::sun::star
;
41 static void aBasicErrorFunc( const OUString
&rErr
, const OUString
&rAction
)
43 OString aErr
= "Unexpected dialog: " +
44 OUStringToOString( rAction
, RTL_TEXTENCODING_ASCII_US
) +
46 OUStringToOString( rErr
, RTL_TEXTENCODING_ASCII_US
);
47 CPPUNIT_ASSERT_MESSAGE( aErr
.getStr(), false);
50 // NB. this constructor is called before any tests are run, once for each
51 // test function in a rather non-intuitive way. This is why all the 'real'
52 // heavy lifting is deferred until setUp. setUp and tearDown are interleaved
53 // between the tests as you might expect.
54 test::BootstrapFixture::BootstrapFixture( bool bAssertOnDialog
, bool bNeedUCB
)
55 : m_bNeedUCB( bNeedUCB
)
56 , m_bAssertOnDialog( bAssertOnDialog
)
63 static void test_init_impl(bool bAssertOnDialog
, bool bNeedUCB
,
64 lang::XMultiServiceFactory
* pSFactory
)
67 ErrorRegistry::RegisterDisplay( aBasicErrorFunc
);
69 // Make GraphicConverter work, normally done in desktop::Desktop::Main()
70 Application::SetFilterHdl(
71 LINK(nullptr, test::BootstrapFixture
, ImplInitFilterHdl
));
75 // initialise unconfigured UCB:
76 uno::Reference
<ucb::XUniversalContentBroker
> xUcb(pSFactory
->createInstance("com.sun.star.ucb.UniversalContentBroker"), uno::UNO_QUERY_THROW
);
77 uno::Reference
<ucb::XContentProvider
> xFileProvider(pSFactory
->createInstance("com.sun.star.ucb.FileContentProvider"), uno::UNO_QUERY_THROW
);
78 xUcb
->registerContentProvider(xFileProvider
, "file", true);
79 uno::Reference
<ucb::XContentProvider
> xTdocProvider(pSFactory
->createInstance("com.sun.star.ucb.TransientDocumentsContentProvider"), uno::UNO_QUERY
);
80 if (xTdocProvider
.is())
82 xUcb
->registerContentProvider(xTdocProvider
, "vnd.sun.star.tdoc", true);
87 // this is called from pyuno
88 SAL_DLLPUBLIC_EXPORT
void test_init(lang::XMultiServiceFactory
*pFactory
)
92 ::comphelper::setProcessServiceFactory(pFactory
);
93 test::setUpVcl(true); // hard-code python tests to headless
94 test_init_impl(false, true, pFactory
);
96 catch (...) { abort(); }
99 // this is called from pyuno
100 SAL_DLLPUBLIC_EXPORT
void test_deinit()
107 void test::BootstrapFixture::setUp()
109 test::BootstrapFixtureBase::setUp();
111 test_init_impl(m_bAssertOnDialog
, m_bNeedUCB
, m_xSFactory
.get());
113 #if OSL_DEBUG_LEVEL > 0
114 Scheduler::ProcessEventsToIdle();
117 mxComponentContext
.set(comphelper::getComponentContext(getMultiServiceFactory()));
120 test::BootstrapFixture::~BootstrapFixture()
124 #if HAVE_EXPORT_VALIDATION
127 OString
loadFile(const OUString
& rURL
)
129 osl::File
aFile(rURL
);
130 osl::FileBase::RC eStatus
= aFile
.open(osl_File_OpenFlag_Read
);
131 CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None
, eStatus
);
133 aFile
.getSize(nSize
);
134 std::unique_ptr
<char[]> aBytes(new char[nSize
]);
135 sal_uInt64 nBytesRead
;
136 aFile
.read(aBytes
.get(), nSize
, nBytesRead
);
137 CPPUNIT_ASSERT_EQUAL(nSize
, nBytesRead
);
138 OString
aContent(aBytes
.get(), nBytesRead
);
146 void test::BootstrapFixture::validate(const OUString
& rPath
, test::ValidationFormat eFormat
) const
148 #if HAVE_EXPORT_VALIDATION
150 if( eFormat
== test::OOXML
)
154 else if ( eFormat
== test::ODF
)
156 var
= "ODFVALIDATOR";
158 else if ( eFormat
== test::MSBINARY
)
160 #if HAVE_BFFVALIDATOR
161 var
= "BFFVALIDATOR";
163 // Binary Format Validator is disabled
168 oslProcessError e
= osl_getEnvironment(var
.pData
, &aValidator
.pData
);
169 CPPUNIT_ASSERT_EQUAL_MESSAGE(
170 OUString("cannot get env var " + var
).toUtf8().getStr(),
171 osl_Process_E_None
, e
);
172 CPPUNIT_ASSERT_MESSAGE(
173 OUString("empty get env var " + var
).toUtf8().getStr(),
174 !aValidator
.isEmpty());
176 if (eFormat
== test::ODF
)
178 // invoke without -e so that we know when something new is written
179 // in loext namespace that isn't yet in the custom schema
181 + m_directories
.getPathFromSrc(u
"/schema/libreoffice/OpenDocument-v1.3+libreoffice-manifest-schema.rng")
183 + m_directories
.getPathFromSrc(u
"/schema/libreoffice/OpenDocument-v1.3+libreoffice-dsig-schema.rng")
185 + m_directories
.getPathFromSrc(u
"/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng")
187 + m_directories
.getPathFromSrc(u
"/schema/mathml2/mathml2.xsd");
190 utl::TempFileNamed aOutput
;
191 aOutput
.EnableKillingFile();
192 OUString aOutputFile
= aOutput
.GetFileName();
193 OUString aCommand
= aValidator
+ " " + rPath
+ " > " + aOutputFile
+ " 2>&1";
196 // For now, this is only needed by some Linux ASan builds, so keep it simply and disable it on
197 // Windows (which doesn't support the relevant shell syntax for (un-)setting environment
200 if (test::getArgument(u
"env", &env
)) {
201 auto const n
= env
.indexOf('=');
203 aCommand
= "unset -v " + env
+ " && " + aCommand
;
205 aCommand
= env
+ " " + aCommand
;
210 SAL_INFO("test", "BootstrapFixture::validate: executing '" << aCommand
<< "'");
211 int returnValue
= system(OUStringToOString(aCommand
, RTL_TEXTENCODING_UTF8
).getStr());
213 OString aContentString
= loadFile(aOutput
.GetURL());
214 OUString aContentOUString
= OStringToOUString(aContentString
, RTL_TEXTENCODING_UTF8
);
216 if( eFormat
== test::OOXML
&& !aContentOUString
.isEmpty() )
218 // check for validation errors here
219 sal_Int32 nIndex
= aContentOUString
.lastIndexOf("Grand total of errors in submitted package: ");
222 SAL_WARN("test", "no summary line");
226 sal_Int32 nStartOfNumber
= nIndex
+ std::strlen("Grand total of errors in submitted package: ");
227 std::u16string_view aNumber
= aContentOUString
.subView(nStartOfNumber
);
228 sal_Int32 nErrors
= o3tl::toInt32(aNumber
);
229 OString aMsg
= "validation error in OOXML export: Errors: " + OString::number(nErrors
);
232 SAL_WARN("test", aContentOUString
);
234 CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg
.getStr(), sal_Int32(0), nErrors
);
237 else if( eFormat
== test::ODF
&& !aContentOUString
.isEmpty() )
239 if( aContentOUString
.indexOf("Error") != -1 )
241 SAL_WARN("test", aContentOUString
);
242 CPPUNIT_FAIL(aContentString
.getStr());
245 CPPUNIT_ASSERT_EQUAL_MESSAGE(
247 "failed to execute: " + OUStringToOString(aCommand
, RTL_TEXTENCODING_UTF8
) + "\n"
248 + OUStringToOString(aContentOUString
, RTL_TEXTENCODING_UTF8
)).getStr(),
257 test::BootstrapFixture
, ImplInitFilterHdl
, ConvertData
&, rData
, bool)
259 return GraphicFilter::GetGraphicFilter().GetFilterCallback().Call( rData
);
262 bool test::BootstrapFixture::IsDefaultDPI()
264 return (Application::GetDefaultDevice()->GetDPIX() == 96
265 && Application::GetDefaultDevice()->GetDPIY() == 96);
268 std::pair
<double, double> test::BootstrapFixture::getDPIScaling()
270 return { Application::GetDefaultDevice()->GetDPIX() / 96.0,
271 Application::GetDefaultDevice()->GetDPIY() / 96.0 };
274 sal_uInt16
test::BootstrapFixture::getDefaultDeviceBitCount()
276 ScopedVclPtr
<VirtualDevice
> device
277 = VclPtr
<VirtualDevice
>::Create(DeviceFormat::WITHOUT_ALPHA
);
278 return device
->GetBitCount();
281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */