LibreOffice Module test (master)  1
bootstrapfixture.cxx
Go to the documentation of this file.
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 
10 #include <config_features.h>
11 
13 #include <vcl/errinf.hxx>
14 #include <sal/log.hxx>
16 
17 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
18 #include <com/sun/star/ucb/XContentProvider.hpp>
19 #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
20 
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 
33 #include <memory>
34 #include <cstring>
35 
36 #include "setupvcl.hxx"
37 
38 using namespace ::com::sun::star;
39 
40 static void aBasicErrorFunc( const OUString &rErr, const OUString &rAction )
41 {
42  OString aErr = "Unexpected dialog: " +
43  OUStringToOString( rAction, RTL_TEXTENCODING_ASCII_US ) +
44  " Error: " +
45  OUStringToOString( rErr, RTL_TEXTENCODING_ASCII_US );
46  CPPUNIT_ASSERT_MESSAGE( aErr.getStr(), false);
47 }
48 
49 // NB. this constructor is called before any tests are run, once for each
50 // test function in a rather non-intuitive way. This is why all the 'real'
51 // heavy lifting is deferred until setUp. setUp and tearDown are interleaved
52 // between the tests as you might expect.
53 test::BootstrapFixture::BootstrapFixture( bool bAssertOnDialog, bool bNeedUCB )
54  : m_bNeedUCB( bNeedUCB )
55  , m_bAssertOnDialog( bAssertOnDialog )
56 {
57 }
58 
59 extern "C"
60 {
61 
62 static void test_init_impl(bool bAssertOnDialog, bool bNeedUCB,
63  lang::XMultiServiceFactory * pSFactory)
64 {
65  if (bAssertOnDialog)
67 
68  // Make GraphicConverter work, normally done in desktop::Desktop::Main()
70  LINK(nullptr, test::BootstrapFixture, ImplInitFilterHdl));
71 
72  if (bNeedUCB)
73  {
74  // initialise unconfigured UCB:
75  uno::Reference<ucb::XUniversalContentBroker> xUcb(pSFactory->createInstance("com.sun.star.ucb.UniversalContentBroker"), uno::UNO_QUERY_THROW);
76  uno::Reference<ucb::XContentProvider> xFileProvider(pSFactory->createInstance("com.sun.star.ucb.FileContentProvider"), uno::UNO_QUERY_THROW);
77  xUcb->registerContentProvider(xFileProvider, "file", true);
78  uno::Reference<ucb::XContentProvider> xTdocProvider(pSFactory->createInstance("com.sun.star.ucb.TransientDocumentsContentProvider"), uno::UNO_QUERY);
79  if (xTdocProvider.is())
80  {
81  xUcb->registerContentProvider(xTdocProvider, "vnd.sun.star.tdoc", true);
82  }
83  }
84 }
85 
86 // this is called from pyuno
87 SAL_DLLPUBLIC_EXPORT void test_init(lang::XMultiServiceFactory *pFactory)
88 {
89  try
90  {
91  ::comphelper::setProcessServiceFactory(pFactory);
92  test::setUpVcl(true); // hard-code python tests to headless
93  test_init_impl(false, true, pFactory);
94  }
95  catch (...) { abort(); }
96 }
97 
98 // this is called from pyuno
99 SAL_DLLPUBLIC_EXPORT void test_deinit()
100 {
101  DeInitVCL();
102 }
103 
104 } // extern "C"
105 
107 {
109 
110  test_init_impl(m_bAssertOnDialog, m_bNeedUCB, m_xSFactory.get());
111 
112 #if OSL_DEBUG_LEVEL > 0
114 #endif
115 
116  mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
117 }
118 
120 {
121 }
122 
123 #if HAVE_EXPORT_VALIDATION
124 namespace {
125 
126 OString loadFile(const OUString& rURL)
127 {
128  osl::File aFile(rURL);
129  osl::FileBase::RC eStatus = aFile.open(osl_File_OpenFlag_Read);
130  CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, eStatus);
131  sal_uInt64 nSize;
132  aFile.getSize(nSize);
133  std::unique_ptr<char[]> aBytes(new char[nSize]);
134  sal_uInt64 nBytesRead;
135  aFile.read(aBytes.get(), nSize, nBytesRead);
136  CPPUNIT_ASSERT_EQUAL(nSize, nBytesRead);
137  OString aContent(aBytes.get(), nBytesRead);
138 
139  return aContent;
140 }
141 
142 }
143 #endif
144 
145 void test::BootstrapFixture::validate(const OUString& rPath, test::ValidationFormat eFormat) const
146 {
147 #if HAVE_EXPORT_VALIDATION
148  OUString var;
149  if( eFormat == test::OOXML )
150  {
151  var = "OFFICEOTRON";
152  }
153  else if ( eFormat == test::ODF )
154  {
155  var = "ODFVALIDATOR";
156  }
157  else if ( eFormat == test::MSBINARY )
158  {
159 #if HAVE_BFFVALIDATOR
160  var = "BFFVALIDATOR";
161 #else
162  // Binary Format Validator is disabled
163  return;
164 #endif
165  }
166  OUString aValidator;
167  oslProcessError e = osl_getEnvironment(var.pData, &aValidator.pData);
168  CPPUNIT_ASSERT_EQUAL_MESSAGE(
169  OUString("cannot get env var " + var).toUtf8().getStr(),
170  osl_Process_E_None, e);
171  CPPUNIT_ASSERT_MESSAGE(
172  OUString("empty get env var " + var).toUtf8().getStr(),
173  !aValidator.isEmpty());
174 
175  if (eFormat == test::ODF)
176  {
177  // invoke without -e so that we know when something new is written
178  // in loext namespace that isn't yet in the custom schema
179  aValidator += " -M "
180  + m_directories.getPathFromSrc(u"/schema/libreoffice/OpenDocument-v1.3+libreoffice-manifest-schema.rng")
181  + " -D "
182  + m_directories.getPathFromSrc(u"/schema/libreoffice/OpenDocument-v1.3+libreoffice-dsig-schema.rng")
183  + " -O "
184  + m_directories.getPathFromSrc(u"/schema/libreoffice/OpenDocument-v1.3+libreoffice-schema.rng")
185  + " -m "
186  + m_directories.getPathFromSrc(u"/schema/mathml2/mathml2.xsd");
187  }
188 
189  utl::TempFile aOutput;
190  aOutput.EnableKillingFile();
191  OUString aOutputFile = aOutput.GetFileName();
192  OUString aCommand = aValidator + " " + rPath + " > " + aOutputFile + " 2>&1";
193 
194 #if !defined _WIN32
195  // For now, this is only needed by some Linux ASan builds, so keep it simply and disable it on
196  // Windows (which doesn't support the relevant shell syntax for (un-)setting environment
197  // variables).
198  OUString env;
199  if (test::getArgument(u"env", &env)) {
200  auto const n = env.indexOf('=');
201  if (n == -1) {
202  aCommand = "unset -v " + env + " && " + aCommand;
203  } else {
204  aCommand = env + " " + aCommand;
205  }
206  }
207 #endif
208 
209  SAL_INFO("test", "BootstrapFixture::validate: executing '" << aCommand << "'");
210  int returnValue = system(OUStringToOString(aCommand, RTL_TEXTENCODING_UTF8).getStr());
211 
212  OString aContentString = loadFile(aOutput.GetURL());
213  OUString aContentOUString = OStringToOUString(aContentString, RTL_TEXTENCODING_UTF8);
214 
215  if( eFormat == test::OOXML && !aContentOUString.isEmpty() )
216  {
217  // check for validation errors here
218  sal_Int32 nIndex = aContentOUString.lastIndexOf("Grand total of errors in submitted package: ");
219  if(nIndex == -1)
220  {
221  SAL_WARN("test", "no summary line");
222  }
223  else
224  {
225  sal_Int32 nStartOfNumber = nIndex + std::strlen("Grand total of errors in submitted package: ");
226  OUString aNumber = aContentOUString.copy(nStartOfNumber);
227  sal_Int32 nErrors = aNumber.toInt32();
228  OString aMsg = "validation error in OOXML export: Errors: " + OString::number(nErrors);
229  if(nErrors)
230  {
231  SAL_WARN("test", aContentOUString);
232  }
233  CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_Int32(0), nErrors);
234  }
235  }
236  else if( eFormat == test::ODF && !aContentOUString.isEmpty() )
237  {
238  if( aContentOUString.indexOf("Error") != -1 )
239  {
240  SAL_WARN("test", aContentOUString);
241  CPPUNIT_FAIL(aContentString.getStr());
242  }
243  }
244  CPPUNIT_ASSERT_EQUAL_MESSAGE(
245  OString(
246  "failed to execute: " + OUStringToOString(aCommand, RTL_TEXTENCODING_UTF8) + "\n"
247  + OUStringToOString(aContentOUString, RTL_TEXTENCODING_UTF8)).getStr(),
248  0, returnValue);
249 #else
250  (void)rPath;
251  (void)eFormat;
252 #endif
253 }
254 
256  test::BootstrapFixture, ImplInitFilterHdl, ConvertData&, rData, bool)
257 {
259 }
260 
262 {
263  return (Application::GetDefaultDevice()->GetDPIX() == 96
264  && Application::GetDefaultDevice()->GetDPIY() == 96);
265 }
266 
268 {
270  = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
271  return device->GetBitCount();
272 }
273 
274 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static sal_uInt16 getDefaultDeviceBitCount()
static void test_init_impl(bool bAssertOnDialog, bool bNeedUCB, lang::XMultiServiceFactory *pSFactory)
sal_Int32 nIndex
sal_Int64 n
const ContentProperties & rData
exports com.sun.star. system
OOO_DLLPUBLIC_TEST_SETUPVCL void setUpVcl(bool forceHeadless=false)
Definition: setupvcl.cxx:73
SAL_DLLPUBLIC_EXPORT void test_deinit()
static OutputDevice * GetDefaultDevice()
bool getArgument(std::u16string_view name, OUString *value)
static void SetFilterHdl(const Link< ConvertData &, bool > &rLink)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
OUString const & GetURL() const
float u
SAL_DLLPUBLIC_EXPORT void test_init(lang::XMultiServiceFactory *pFactory)
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
Link< ConvertData &, bool > GetFilterCallback() const
static void aBasicErrorFunc(const OUString &rErr, const OUString &rAction)
virtual void setUp() override
void validate(const OUString &rURL, ValidationFormat) const
virtual void setUp() override
OUString GetFileName() const
#define SAL_INFO(area, stream)
static VclPtr< reference_type > Create(Arg &&...arg)
static void ProcessEventsToIdle()
static void RegisterDisplay(BasicDisplayErrorFunc *)
static GraphicFilter & GetGraphicFilter()
#define SAL_WARN(area, stream)
OUString aCommand
IMPL_STATIC_LINK(test::BootstrapFixture, ImplInitFilterHdl, ConvertData &, rData, bool)
VCL_DLLPUBLIC void DeInitVCL()
BootstrapFixture(bool bAssertOnDialog=true, bool bNeedUCB=true)
void EnableKillingFile(bool bEnable=true)
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo
virtual ~BootstrapFixture() override