xref: /trunk/main/unoxml/test/domtest.cxx (revision e9cbe144)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // autogenerated file with codegen.pl
25 
26 #include <testshl/simpleheader.hxx>
27 
28 #include <rtl/ref.hxx>
29 #include <osl/file.hxx>
30 #include <osl/process.h>
31 #include <comphelper/seqstream.hxx>
32 #include <comphelper/sequence.hxx>
33 #include <cppuhelper/compbase1.hxx>
34 #include <cppuhelper/bootstrap.hxx>
35 #include <cppuhelper/basemutex.hxx>
36 
37 #include <com/sun/star/xml/sax/FastToken.hpp>
38 #include <com/sun/star/xml/sax/XSAXSerializable.hpp>
39 #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
40 
41 #include "../source/dom/documentbuilder.hxx"
42 
43 
44 using namespace ::DOM;
45 using namespace ::comphelper;
46 using namespace ::com::sun::star;
47 
48 namespace
49 {
50 
51 // valid xml
52 static const char validTestFile[] =
53 "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \
54  <office:document-content \
55    xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" \
56    xmlns:xlink=\"http://www.w3.org/1999/xlink\" \
57    office:version=\"1.0\"> \
58    <office:scripts/> \
59    <xlink:test/> \
60    <office:automatic-styles teststyle=\"test\"/> \
61    <moretest/> \
62     some text öäü \
63  </office:document-content> \
64 ";
65 
66 // generates a warning: unsupported xml version, unknown xml:space
67 // value
68 static const char warningTestFile[] =
69 "<?xml version=\"47-11.0\" encoding=\"UTF-8\"?> \
70  <office:document-content \
71    xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" \
72    xml:space=\"blafasl\" \
73    office:version=\"1.0\"> \
74    <office:scripts/> \
75    <office:automatic-styles/> \
76  </office:document-content> \
77 ";
78 
79 // <?xml not at start of file
80 static const char errorTestFile[] =
81 " <?xml version=\"1.0\" encoding=\"UTF-8\"?> \
82  <office:document-content \
83    xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" \
84    office:version=\"1.0\"> \
85    <office:scripts/> \
86    <office:automatic-styles/> \
87  </office:document-content> \
88 ";
89 
90 // plain empty
91 static const char fatalTestFile[] = "";
92 
93 struct ErrorHandler
94     : public ::cppu::WeakImplHelper1< xml::sax::XErrorHandler >
95 {
96     sal_uInt32 mnErrCount;
97     sal_uInt32 mnFatalCount;
98     sal_uInt32 mnWarnCount;
99 
100     bool noErrors() const { return !mnErrCount && !mnFatalCount && !mnWarnCount; }
101 
102     ErrorHandler() : mnErrCount(0), mnFatalCount(0), mnWarnCount(0)
103     {}
104 
105     virtual void SAL_CALL error( const uno::Any& ) throw (xml::sax::SAXException, uno::RuntimeException)
106     {
107         ++mnErrCount;
108     }
109 
110     virtual void SAL_CALL fatalError( const uno::Any& ) throw (xml::sax::SAXException, uno::RuntimeException)
111     {
112         ++mnFatalCount;
113     }
114 
115     virtual void SAL_CALL warning( const uno::Any& ) throw (xml::sax::SAXException, uno::RuntimeException)
116     {
117         ++mnWarnCount;
118     }
119 };
120 
121 struct DocumentHandler
122     : public ::cppu::WeakImplHelper1< xml::sax::XFastDocumentHandler >
123 {
124     // XFastContextHandler
125     virtual void SAL_CALL startFastElement( ::sal_Int32 Element, const uno::Reference< xml::sax::XFastAttributeList >& Attribs ) throw (xml::sax::SAXException, uno::RuntimeException)
126     {
127         OSL_TRACE("Seen element: %c with namespace 0x%x",
128                   Element & 0xFFFF, Element & 0xFFFF0000);
129     }
130 
131     virtual void SAL_CALL startUnknownElement( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name, const uno::Reference< xml::sax::XFastAttributeList >& Attribs ) throw (xml::sax::SAXException, uno::RuntimeException)
132     {
133     }
134 
135     virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (xml::sax::SAXException, uno::RuntimeException)
136     {
137     }
138 
139     virtual void SAL_CALL endUnknownElement( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name ) throw (xml::sax::SAXException, uno::RuntimeException)
140     {
141     }
142 
143     virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const uno::Reference< xml::sax::XFastAttributeList >& Attribs ) throw (xml::sax::SAXException, uno::RuntimeException)
144     {
145         return this;
146     }
147 
148     virtual uno::Reference< xml::sax::XFastContextHandler > SAL_CALL createUnknownChildContext( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name, const uno::Reference< xml::sax::XFastAttributeList >& Attribs ) throw (xml::sax::SAXException, uno::RuntimeException)
149     {
150         return this;
151     }
152 
153     virtual void SAL_CALL characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException)
154     {
155     }
156 
157     // XFastDocumentHandler
158     virtual void SAL_CALL startDocument(  ) throw (xml::sax::SAXException, uno::RuntimeException)
159     {
160     }
161 
162     virtual void SAL_CALL endDocument(  ) throw (xml::sax::SAXException, uno::RuntimeException)
163     {
164     }
165 
166     virtual void SAL_CALL setDocumentLocator( const uno::Reference< xml::sax::XLocator >& xLocator ) throw (xml::sax::SAXException, uno::RuntimeException)
167     {
168     }
169 };
170 
171 struct TokenHandler
172     : public ::cppu::WeakImplHelper1< xml::sax::XFastTokenHandler >
173 {
174     virtual ::sal_Int32 SAL_CALL getToken( const ::rtl::OUString& Identifier ) throw (uno::RuntimeException)
175     {
176         CPPUNIT_ASSERT_MESSAGE( "TokenHandler::getToken() unexpected call",
177                                 false );
178         return -1;
179     }
180 
181     virtual ::rtl::OUString SAL_CALL getIdentifier( ::sal_Int32 Token ) throw (uno::RuntimeException)
182     {
183         CPPUNIT_ASSERT_MESSAGE( "TokenHandler::getIdentifier() unexpected call",
184                                 false );
185         return rtl::OUString();
186     }
187 
188     virtual ::sal_Int32 SAL_CALL getTokenFromUTF8( const uno::Sequence< ::sal_Int8 >& Identifier ) throw (uno::RuntimeException)
189     {
190         OSL_TRACE("getTokenFromUTF8() %s", (const char*)Identifier.getConstArray());
191         return Identifier.getLength() ? Identifier[0] : 0;
192     }
193 
194     virtual uno::Sequence< ::sal_Int8 > SAL_CALL getUTF8Identifier( ::sal_Int32 Token ) throw (uno::RuntimeException)
195     {
196         CPPUNIT_ASSERT_MESSAGE( "TokenHandler::getUTF8Identifier() unexpected call",
197                                 false );
198         return uno::Sequence<sal_Int8>();
199     }
200 };
201 
202 struct BasicTest : public CppUnit::TestFixture
203 {
204     rtl::Reference<CDocumentBuilder>    mxDomBuilder;
205     rtl::Reference<ErrorHandler>        mxErrHandler;
206     rtl::Reference<SequenceInputStream> mxValidInStream;
207     rtl::Reference<SequenceInputStream> mxWarningInStream;
208     rtl::Reference<SequenceInputStream> mxErrorInStream;
209     rtl::Reference<SequenceInputStream> mxFatalInStream;
210 
211     void setUp()
212     {
213         // luckily, DOM builder doesn't use service fac, so we need
214         // not bootstrap uno here
215         mxErrHandler.set( new ErrorHandler() );
216         mxDomBuilder.set( new CDocumentBuilder(Reference< XMultiServiceFactory >() ));
217         mxValidInStream.set( new SequenceInputStream(ByteSequence((sal_Int8*)validTestFile,
218                                                                   sizeof(validTestFile)/sizeof(*validTestFile))) );
219         mxWarningInStream.set( new SequenceInputStream(ByteSequence((sal_Int8*)warningTestFile,
220                                                                     sizeof(warningTestFile)/sizeof(*warningTestFile))) );
221         mxErrorInStream.set( new SequenceInputStream(ByteSequence((sal_Int8*)errorTestFile,
222                                                                   sizeof(errorTestFile)/sizeof(*errorTestFile))) );
223         mxFatalInStream.set( new SequenceInputStream(ByteSequence((sal_Int8*)fatalTestFile,
224                                                                   sizeof(fatalTestFile)/sizeof(*fatalTestFile))) );
225         mxDomBuilder->setErrorHandler(mxErrHandler.get());
226     }
227 
228     void validInputTest()
229     {
230         CPPUNIT_ASSERT_MESSAGE( "Valid input file did not result in XDocument #1",
231                                 mxDomBuilder->parse(
232                                     uno::Reference<io::XInputStream>(
233                                         mxValidInStream.get())).is() );
234         CPPUNIT_ASSERT_MESSAGE( "Valid input file resulted in parse errors",
235                                 mxErrHandler->noErrors() );
236     }
237 
238     void warningInputTest()
239     {
240         CPPUNIT_ASSERT_MESSAGE( "Valid input file did not result in XDocument #2",
241                                 mxDomBuilder->parse(
242                                     uno::Reference<io::XInputStream>(
243                                         mxWarningInStream.get())).is() );
244         CPPUNIT_ASSERT_MESSAGE( "No parse warnings in unclean input file",
245                                 mxErrHandler->mnWarnCount && !mxErrHandler->mnErrCount && !mxErrHandler->mnFatalCount );
246     }
247 
248     void errorInputTest()
249     {
250         CPPUNIT_ASSERT_MESSAGE( "Valid input file did not result in XDocument #3",
251                                 mxDomBuilder->parse(
252                                     uno::Reference<io::XInputStream>(
253                                         mxErrorInStream.get())).is() );
254         CPPUNIT_ASSERT_MESSAGE( "No parse errors in unclean input file",
255                                 !mxErrHandler->mnWarnCount && mxErrHandler->mnErrCount && !mxErrHandler->mnFatalCount );
256     }
257 
258     void fatalInputTest()
259     {
260         CPPUNIT_ASSERT_MESSAGE( "Broken input file resulted in XDocument",
261                                 !mxDomBuilder->parse(
262                                     uno::Reference<io::XInputStream>(
263                                         mxFatalInStream.get())).is() );
264         CPPUNIT_ASSERT_MESSAGE( "No fatal parse errors in unclean input file",
265                                 !mxErrHandler->mnWarnCount && !mxErrHandler->mnErrCount && mxErrHandler->mnFatalCount );
266     };
267 
268     // Change the following lines only, if you add, remove or rename
269     // member functions of the current class,
270     // because these macros are need by auto register mechanism.
271     CPPUNIT_TEST_SUITE(BasicTest);
272     CPPUNIT_TEST(validInputTest);
273     CPPUNIT_TEST(warningInputTest);
274     CPPUNIT_TEST(errorInputTest);
275     CPPUNIT_TEST(fatalInputTest);
276     CPPUNIT_TEST_SUITE_END();
277 };
278 
279 struct SerializerTest : public CppUnit::TestFixture
280 {
281     SerializerTest() : mbUnoInitialized(false) {}
282 
283     uno::Reference<uno::XComponentContext>                   mxCtx;
284     rtl::Reference<CDocumentBuilder>                         mxDomBuilder;
285     rtl::Reference<ErrorHandler>                             mxErrHandler;
286     rtl::Reference<SequenceInputStream>                      mxInStream;
287     rtl::Reference<DocumentHandler>                          mxHandler;
288     rtl::Reference<TokenHandler>                             mxTokHandler;
289     uno::Sequence< beans::Pair< rtl::OUString, sal_Int32 > > maRegisteredNamespaces;
290     bool                                                     mbUnoInitialized;
291 
292     void setUp()
293     {
294         // need working typelib, bootstrap UNO now
295         if( !mbUnoInitialized )
296         {
297             const char* pArgs( getForwardString() );
298             CPPUNIT_ASSERT_MESSAGE("Test file parameter", pArgs);
299 
300             const rtl::OUString sBaseDir=rtl::OUString::createFromAscii(pArgs);
301 
302             // bootstrap UNO
303             try
304             {
305                 ::rtl::OUString aIniUrl;
306                 CPPUNIT_ASSERT_MESSAGE(
307                     "Converting ini file to URL",
308                     osl_getFileURLFromSystemPath(
309                         (sBaseDir+rtl::OUString::createFromAscii("unoxml_unittest_test.ini")).pData,
310                         &aIniUrl.pData ) == osl_File_E_None );
311 
312                 mxCtx = ::cppu::defaultBootstrap_InitialComponentContext(aIniUrl);
313                 CPPUNIT_ASSERT_MESSAGE("Getting component context", mxCtx.is());
314             }
315             catch( uno::Exception& )
316             {
317                 CPPUNIT_ASSERT_MESSAGE("Bootstrapping UNO", false);
318             }
319 
320             mbUnoInitialized = true;
321         }
322 
323         mxErrHandler.set( new ErrorHandler() );
324         mxDomBuilder.set( new CDocumentBuilder(
325                               uno::Reference< lang::XMultiServiceFactory >(
326                                   mxCtx->getServiceManager(),
327                                   uno::UNO_QUERY )));
328         mxInStream.set( new SequenceInputStream(ByteSequence((sal_Int8*)validTestFile,
329                                                              sizeof(validTestFile)/sizeof(*validTestFile))) );
330         mxDomBuilder->setErrorHandler(mxErrHandler.get());
331 
332         mxHandler.set( new DocumentHandler() );
333         mxTokHandler.set( new TokenHandler() );
334 
335         maRegisteredNamespaces.realloc(2);
336         maRegisteredNamespaces[0] = beans::make_Pair(
337             rtl::OUString(
338                 RTL_CONSTASCII_USTRINGPARAM(
339                     "urn:oasis:names:tc:opendocument:xmlns:office:1.0") ),
340             xml::sax::FastToken::NAMESPACE);
341         maRegisteredNamespaces[1] = beans::make_Pair(
342             rtl::OUString(
343                 RTL_CONSTASCII_USTRINGPARAM(
344                     "http://www.w3.org/1999/xlink") ),
345             2*xml::sax::FastToken::NAMESPACE);
346     }
347 
348     void serializerTest ()
349     {
350         uno::Reference< xml::dom::XDocument > xDoc=
351             mxDomBuilder->parse(
352                 uno::Reference<io::XInputStream>(
353                     mxInStream.get()));
354         CPPUNIT_ASSERT_MESSAGE( "Valid input file did not result in XDocument",
355                                 xDoc.is() );
356         CPPUNIT_ASSERT_MESSAGE( "Valid input file resulted in parse errors",
357                                 mxErrHandler->noErrors() );
358 
359         uno::Reference< xml::sax::XSAXSerializable > xSaxSerializer(
360             xDoc, uno::UNO_QUERY);
361         CPPUNIT_ASSERT_MESSAGE( "XSAXSerializable not supported",
362                                 xSaxSerializer.is() );
363 
364         uno::Reference< xml::sax::XFastSAXSerializable > xFastSaxSerializer(
365             xDoc, uno::UNO_QUERY);
366         CPPUNIT_ASSERT_MESSAGE( "XFastSAXSerializable not supported",
367                                 xSaxSerializer.is() );
368 
369         xFastSaxSerializer->fastSerialize( mxHandler.get(),
370                                            mxTokHandler.get(),
371                                            uno::Sequence< beans::StringPair >(),
372                                            maRegisteredNamespaces );
373     }
374 
375     // Change the following lines only, if you add, remove or rename
376     // member functions of the current class,
377     // because these macros are need by auto register mechanism.
378 
379     CPPUNIT_TEST_SUITE(SerializerTest);
380     CPPUNIT_TEST(serializerTest);
381     CPPUNIT_TEST_SUITE_END();
382 };
383 
384 // -----------------------------------------------------------------------------
385 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(BasicTest, "BasicTest");
386 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SerializerTest, "SerializerTest");
387 }
388 
389 
390 // -----------------------------------------------------------------------------
391 
392 // this macro creates an empty function, which will called by the RegisterAllFunctions()
393 // to let the user the possibility to also register some functions by hand.
394 NOADDITIONAL;
395 
396