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 <unotools/tempfile.hxx>
28 #include <vcl/scheduler.hxx>
29 
30 #include <memory>
31 #include <cstring>
32 
33 #include "setupvcl.hxx"
34 
35 using namespace ::com::sun::star;
36 
37 static void aBasicErrorFunc( const OUString &rErr, const OUString &rAction )
38 {
39  OString aErr = "Unexpected dialog: " +
40  OUStringToOString( rAction, RTL_TEXTENCODING_ASCII_US ) +
41  " Error: " +
42  OUStringToOString( rErr, RTL_TEXTENCODING_ASCII_US );
43  CPPUNIT_ASSERT_MESSAGE( aErr.getStr(), false);
44 }
45 
46 // NB. this constructor is called before any tests are run, once for each
47 // test function in a rather non-intuitive way. This is why all the 'real'
48 // heavy lifting is deferred until setUp. setUp and tearDown are interleaved
49 // between the tests as you might expect.
50 test::BootstrapFixture::BootstrapFixture( bool bAssertOnDialog, bool bNeedUCB )
51  : m_bNeedUCB( bNeedUCB )
52  , m_bAssertOnDialog( bAssertOnDialog )
53 {
54 }
55 
56 extern "C"
57 {
58 
59 static void test_init_impl(bool bAssertOnDialog, bool bNeedUCB,
60  lang::XMultiServiceFactory * pSFactory)
61 {
62  if (bAssertOnDialog)
64 
65  // Make GraphicConverter work, normally done in desktop::Desktop::Main()
67  LINK(nullptr, test::BootstrapFixture, ImplInitFilterHdl));
68 
69  if (bNeedUCB)
70  {
71  // initialise unconfigured UCB:
72  uno::Reference<ucb::XUniversalContentBroker> xUcb(pSFactory->createInstance("com.sun.star.ucb.UniversalContentBroker"), uno::UNO_QUERY_THROW);
73  uno::Reference<ucb::XContentProvider> xFileProvider(pSFactory->createInstance("com.sun.star.ucb.FileContentProvider"), uno::UNO_QUERY_THROW);
74  xUcb->registerContentProvider(xFileProvider, "file", true);
75  uno::Reference<ucb::XContentProvider> xTdocProvider(pSFactory->createInstance("com.sun.star.ucb.TransientDocumentsContentProvider"), uno::UNO_QUERY);
76  if (xTdocProvider.is())
77  {
78  xUcb->registerContentProvider(xTdocProvider, "vnd.sun.star.tdoc", true);
79  }
80  }
81 }
82 
83 // this is called from pyuno
84 SAL_DLLPUBLIC_EXPORT void test_init(lang::XMultiServiceFactory *pFactory)
85 {
86  try
87  {
88  ::comphelper::setProcessServiceFactory(pFactory);
89  test::setUpVcl(true); // hard-code python tests to headless
90  test_init_impl(false, true, pFactory);
91  }
92  catch (...) { abort(); }
93 }
94 
95 // this is called from pyuno
96 SAL_DLLPUBLIC_EXPORT void test_deinit()
97 {
98  DeInitVCL();
99 }
100 
101 } // extern "C"
102 
104 {
106 
107  test_init_impl(m_bAssertOnDialog, m_bNeedUCB, m_xSFactory.get());
108 
109 #if OSL_DEBUG_LEVEL > 0
111 #endif
112 
113  mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
114 }
115 
117 {
118 }
119 
120 #if HAVE_EXPORT_VALIDATION
121 namespace {
122 
123 OString loadFile(const OUString& rURL)
124 {
125  osl::File aFile(rURL);
126  osl::FileBase::RC eStatus = aFile.open(osl_File_OpenFlag_Read);
127  CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, eStatus);
128  sal_uInt64 nSize;
129  aFile.getSize(nSize);
130  std::unique_ptr<char[]> aBytes(new char[nSize]);
131  sal_uInt64 nBytesRead;
132  aFile.read(aBytes.get(), nSize, nBytesRead);
133  CPPUNIT_ASSERT_EQUAL(nSize, nBytesRead);
134  OString aContent(aBytes.get(), nBytesRead);
135 
136  return aContent;
137 }
138 
139 }
140 #endif
141 
142 void test::BootstrapFixture::validate(const OUString& rPath, test::ValidationFormat eFormat) const
143 {
144 #if HAVE_EXPORT_VALIDATION
145  OUString var;
146  if( eFormat == test::OOXML )
147  {
148  var = "OFFICEOTRON";
149  }
150  else if ( eFormat == test::ODF )
151  {
152  var = "ODFVALIDATOR";
153  }
154  else if ( eFormat == test::MSBINARY )
155  {
156 #if HAVE_BFFVALIDATOR
157  var = "BFFVALIDATOR";
158 #else
159  // Binary Format Validator is disabled
160  return;
161 #endif
162  }
163  OUString aValidator;
164  oslProcessError e = osl_getEnvironment(var.pData, &aValidator.pData);
165  CPPUNIT_ASSERT_EQUAL_MESSAGE(
166  OUString("cannot get env var " + var).toUtf8().getStr(),
167  osl_Process_E_None, e);
168  CPPUNIT_ASSERT_MESSAGE(
169  OUString("empty get env var " + var).toUtf8().getStr(),
170  !aValidator.isEmpty());
171 
172  if (eFormat == test::ODF)
173  {
174  // invoke without -e so that we know when something new is written
175  // in loext namespace that isn't yet in the custom schema
176  aValidator += " -M "
177  + m_directories.getPathFromSrc(u"/schema/libreoffice/OpenDocument-manifest-schema-v1.3+libreoffice.rng")
178  + " -D "
179  + m_directories.getPathFromSrc(u"/schema/libreoffice/OpenDocument-dsig-schema-v1.3+libreoffice.rng")
180  + " -O "
181  + m_directories.getPathFromSrc(u"/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng")
182  + " -m "
183  + m_directories.getPathFromSrc(u"/schema/mathml2/mathml2.xsd");
184  }
185 
186  utl::TempFile aOutput;
187  aOutput.EnableKillingFile();
188  OUString aOutputFile = aOutput.GetFileName();
189  OUString aCommand = aValidator + " " + rPath + " > " + aOutputFile;
190 
191  SAL_INFO("test", "BootstrapFixture::validate: executing '" << aCommand << "'");
192  int returnValue = system(OUStringToOString(aCommand, RTL_TEXTENCODING_UTF8).getStr());
193 
194  OString aContentString = loadFile(aOutput.GetURL());
195  OUString aContentOUString = OStringToOUString(aContentString, RTL_TEXTENCODING_UTF8);
196 
197  if( eFormat == test::OOXML && !aContentOUString.isEmpty() )
198  {
199  // check for validation errors here
200  sal_Int32 nIndex = aContentOUString.lastIndexOf("Grand total of errors in submitted package: ");
201  if(nIndex == -1)
202  {
203  SAL_WARN("test", "no summary line");
204  }
205  else
206  {
207  sal_Int32 nStartOfNumber = nIndex + std::strlen("Grand total of errors in submitted package: ");
208  OUString aNumber = aContentOUString.copy(nStartOfNumber);
209  sal_Int32 nErrors = aNumber.toInt32();
210  OString aMsg = "validation error in OOXML export: Errors: " + OString::number(nErrors);
211  if(nErrors)
212  {
213  SAL_WARN("test", aContentOUString);
214  }
215  CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_Int32(0), nErrors);
216  }
217  }
218  else if( eFormat == test::ODF && !aContentOUString.isEmpty() )
219  {
220  if( aContentOUString.indexOf("Error") != -1 )
221  {
222  SAL_WARN("test", aContentOUString);
223  CPPUNIT_FAIL(aContentString.getStr());
224  }
225  }
226  CPPUNIT_ASSERT_EQUAL_MESSAGE(
227  OString(
228  "failed to execute: " + OUStringToOString(aCommand, RTL_TEXTENCODING_UTF8) + "\n"
229  + OUStringToOString(aContentOUString, RTL_TEXTENCODING_UTF8)).getStr(),
230  0, returnValue);
231 #else
232  (void)rPath;
233  (void)eFormat;
234 #endif
235 }
236 
238  test::BootstrapFixture, ImplInitFilterHdl, ConvertData&, rData, bool)
239 {
241 }
242 
244 {
245  return (Application::GetDefaultDevice()->GetDPIX() == 96
246  && Application::GetDefaultDevice()->GetDPIY() == 96);
247 }
248 
249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static void test_init_impl(bool bAssertOnDialog, bool bNeedUCB, lang::XMultiServiceFactory *pSFactory)
sal_Int32 nIndex
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()
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 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