2
* Version: MPL 1.1 / GPLv2+ / LGPLv2+
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License or as specified alternatively below. You may obtain a copy of
7
* the License at http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* Major Contributor(s):
15
* Copyright (C) 2011 SUSE <cbosdonnat@suse.com>
18
* All Rights Reserved.
20
* For minor contributions see the git repository.
22
* Alternatively, the contents of this file may be used under the terms of
23
* either the GNU General Public License Version 2 or later (the "GPLv2+"), or
24
* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
25
* in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
26
* instead of those above.
29
#include <cppunit/extensions/HelperMacros.h>
30
#include <cppunit/TestFixture.h>
31
#include <cppunit/TestAssert.h>
32
#include <cppunit/ui/text/TestRunner.h>
34
#include "ws-relatedmultipart.hxx"
35
#include "ws-requests.hxx"
36
#include "ws-soap.hxx"
37
#include "test-helpers.hxx"
41
class SoapTest : public CppUnit::TestFixture
44
map< string, SoapResponseCreator > getTestMapping( );
45
map< string, string > getTestNamespaces( );
46
map< string, SoapFaultDetailCreator > getTestDetailMapping( );
50
// Soap Responses tests
52
void createResponseTest( );
53
void parseFaultDetailEmptyTest( );
54
void parseFaultDetailUnknownTest( );
55
void parseFaultDetailValidTest( );
56
void createFaultDefaultTest( );
57
void parseResponseTest( );
58
void parseResponseFaultTest( );
60
// RelatedMultipart tests
62
void serializeMultipartSimpleTest( );
63
void serializeMultipartComplexTest( );
64
void parseMultipartTest( );
65
void getStreamFromNodeXopTest( );
66
void getStreamFromNodeBase64Test( );
68
// CMISM utilities tests
69
void writeCmismStreamTest( );
71
CPPUNIT_TEST_SUITE( SoapTest );
72
CPPUNIT_TEST( createResponseTest );
73
CPPUNIT_TEST( parseFaultDetailEmptyTest );
74
CPPUNIT_TEST( parseFaultDetailUnknownTest );
75
CPPUNIT_TEST( parseFaultDetailValidTest );
76
CPPUNIT_TEST( parseResponseTest );
77
CPPUNIT_TEST( parseResponseFaultTest );
79
CPPUNIT_TEST( serializeMultipartSimpleTest );
80
CPPUNIT_TEST( serializeMultipartComplexTest );
81
CPPUNIT_TEST( parseMultipartTest );
82
CPPUNIT_TEST( getStreamFromNodeXopTest );
83
CPPUNIT_TEST( getStreamFromNodeBase64Test );
85
CPPUNIT_TEST( writeCmismStreamTest );
87
CPPUNIT_TEST_SUITE_END( );
90
CPPUNIT_TEST_SUITE_REGISTRATION( SoapTest );
92
/** Dummy response class to use for testing
94
class TestResponse : public SoapResponse
101
static SoapResponsePtr create( xmlNodePtr, RelatedMultipart&, SoapSession* )
103
SoapResponsePtr resp ( new TestResponse( ) );
108
class TestFaultDetail : public SoapFaultDetail
111
TestFaultDetail( ) : SoapFaultDetail( ) { };
114
~TestFaultDetail( ) throw ( ) { };
116
static SoapFaultDetailPtr create( xmlNodePtr )
118
return SoapFaultDetailPtr( new TestFaultDetail( ) );
122
map< string, SoapResponseCreator > SoapTest::getTestMapping( )
124
map< string, SoapResponseCreator > mapping;
125
mapping[ "{test-ns-url}testResponse" ] = &TestResponse::create;
129
map< string, SoapFaultDetailCreator > SoapTest::getTestDetailMapping( )
131
map< string, SoapFaultDetailCreator > mapping;
132
mapping[ "{test-ns-url}testFault" ] = &TestFaultDetail::create;
136
map< string, string > SoapTest::getTestNamespaces( )
138
map< string, string > namespaces;
139
namespaces[ "test" ] = "test-ns-url";
143
void SoapTest::createResponseTest( )
145
SoapResponseFactory factory;
146
factory.setMapping( getTestMapping() );
147
factory.setNamespaces( getTestNamespaces( ) );
148
factory.setDetailMapping( getTestDetailMapping( ) );
150
string xml = "<n1:testResponse xmlns:n1=\"test-ns-url\"/>";
151
RelatedMultipart multipart; // Multipart won't be used in that test
153
SoapResponsePtr actual = factory.createResponse( test::getXmlNode( xml ), multipart );
154
CPPUNIT_ASSERT_MESSAGE( "Wrong response created", dynamic_cast< TestResponse* >( actual.get( ) ) != NULL );
157
void SoapTest::parseFaultDetailEmptyTest( )
159
SoapResponseFactory factory;
160
factory.setMapping( getTestMapping() );
161
factory.setNamespaces( getTestNamespaces( ) );
162
factory.setDetailMapping( getTestDetailMapping( ) );
164
string xml = "<detail/>";
166
vector< SoapFaultDetailPtr > actual = factory.parseFaultDetail( test::getXmlNode( xml ) );
167
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Shouldn't have any detail", size_t( 0 ), actual.size() );
170
void SoapTest::parseFaultDetailUnknownTest( )
172
SoapResponseFactory factory;
173
factory.setMapping( getTestMapping() );
174
factory.setNamespaces( getTestNamespaces( ) );
175
factory.setDetailMapping( getTestDetailMapping( ) );
177
string xml = "<detail><unknown-detail/></detail>";
179
vector< SoapFaultDetailPtr > actual = factory.parseFaultDetail( test::getXmlNode( xml ) );
180
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Shouldn't have ignored unknonw details", size_t( 0 ), actual.size() );
182
void SoapTest::parseFaultDetailValidTest( )
184
SoapResponseFactory factory;
185
factory.setMapping( getTestMapping() );
186
factory.setNamespaces( getTestNamespaces( ) );
187
factory.setDetailMapping( getTestDetailMapping( ) );
189
string xml = "<detail><n1:testFault xmlns:n1=\"test-ns-url\"/></detail>";
191
vector< SoapFaultDetailPtr > actual = factory.parseFaultDetail( test::getXmlNode( xml ) );
192
CPPUNIT_ASSERT_MESSAGE( "Wrong fault detail created",
193
dynamic_cast< TestFaultDetail* >( actual.front( ).get( ) ) != NULL );
196
void SoapTest::parseResponseTest( )
198
SoapResponseFactory factory;
199
factory.setMapping( getTestMapping() );
200
factory.setNamespaces( getTestNamespaces( ) );
201
factory.setDetailMapping( getTestDetailMapping( ) );
203
string xml = "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\"><S:Body>"
204
"<test:testResponse xmlns:test=\"test-ns-url\"/>"
205
"<test:testResponse xmlns:test=\"test-ns-url\"/>"
206
"</S:Body></S:Envelope>";
207
string name( "name" );
208
string type( "application/xop+xml" );
209
RelatedPartPtr requestPart( new RelatedPart( name, type, xml ) );
211
RelatedMultipart multipart;
212
string cid = multipart.addPart( requestPart );
213
string startInfo( "text/xml" );
214
multipart.setStart( cid, startInfo );
216
vector< SoapResponsePtr > actual = factory.parseResponse( multipart );
217
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong number of responses", size_t( 2 ), actual.size( ) );
220
void SoapTest::parseResponseFaultTest( )
222
SoapResponseFactory factory;
223
factory.setMapping( getTestMapping() );
224
factory.setNamespaces( getTestNamespaces( ) );
225
factory.setDetailMapping( getTestDetailMapping( ) );
227
string xml = "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\""
228
" xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\""
229
" xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\">"
231
" <faultcode xsi:type=\"xsd:string\">S:Client</faultcode>"
232
" <faultstring xsi:type=\"xsd:string\">Some Error Message</faultstring>"
233
" <detail><n1:testFault xmlns:n1=\"test-ns-url\"/></detail>"
234
" </S:Fault></S:Body>"
237
string name( "name" );
238
string type( "application/xop+xml" );
239
RelatedPartPtr requestPart( new RelatedPart( name, type, xml ) );
241
RelatedMultipart multipart;
242
string cid = multipart.addPart( requestPart );
243
string startInfo( "text/xml" );
244
multipart.setStart( cid, startInfo );
248
factory.parseResponse( multipart );
249
CPPUNIT_FAIL( "Should have thrown the SoapFault" );
251
catch ( const SoapFault& e )
253
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong detail string", string( "Some Error Message" ), e.getFaultstring() );
254
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong detail string", string( "Client" ), e.getFaultcode() );
255
CPPUNIT_ASSERT_MESSAGE( "Wrong fault detail created",
256
dynamic_cast< TestFaultDetail* >( e.getDetail( ).front( ).get( ) ) != NULL );
260
void SoapTest::serializeMultipartSimpleTest( )
262
string partName = "data";
263
string partType = "text/plain";
264
string partContent = "Some content";
265
string startInfo = "some info";
268
RelatedMultipart multipart;
269
RelatedPartPtr part( new RelatedPart( partName, partType, partContent ) );
270
string cid = multipart.addPart( part );
271
multipart.setStart( cid, startInfo );
273
boost::shared_ptr< istringstream > actual = multipart.toStream( );
275
string boundary = multipart.getBoundary( );
276
string expected = "\r\n--" + boundary + "\r\n" +
277
"Content-Id: <" + cid + ">\r\n" +
278
"Content-Type: " + partType + "\r\n" +
279
"Content-Transfer-Encoding: binary\r\n" +
282
"\r\n--" + boundary + "--\r\n";
284
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong body", expected, actual->str() );
285
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong content type",
286
"multipart/related;start=\"" + cid + "\";type=\"" + partType + "\";boundary=\"" + boundary + "\";start-info=\"" + startInfo + "\"",
287
multipart.getContentType() );
290
void SoapTest::serializeMultipartComplexTest( )
292
string rootName = "root";
293
string rootType = "text/plain";
294
string rootContent = "Some content";
296
string part2Name = "part2";
297
string part2Type = "application/octet-stream";
298
string part2Content = "Some content 2";
300
string startInfo = "some info";
303
RelatedMultipart multipart;
304
RelatedPartPtr rootPart( new RelatedPart( rootName, rootType, rootContent ) );
305
string rootCid = multipart.addPart( rootPart );
307
RelatedPartPtr part2( new RelatedPart( part2Name, part2Type, part2Content ) );
308
string part2Cid = multipart.addPart( part2 );
310
multipart.setStart( rootCid, startInfo );
312
boost::shared_ptr< istringstream > actual = multipart.toStream( );
314
string boundary = multipart.getBoundary( );
315
string expected = "\r\n--" + boundary + "\r\n" +
316
"Content-Id: <" + rootCid + ">\r\n" +
317
"Content-Type: " + rootType + "\r\n" +
318
"Content-Transfer-Encoding: binary\r\n" +
321
"\r\n--" + boundary + "\r\n" +
322
"Content-Id: <" + part2Cid + ">\r\n" +
323
"Content-Type: " + part2Type + "\r\n" +
324
"Content-Transfer-Encoding: binary\r\n" +
327
"\r\n--" + boundary + "--\r\n";
329
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong body", expected, actual->str() );
330
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong content type",
331
"multipart/related;start=\"" + rootCid + "\";type=\"" + rootType + "\";boundary=\"" + boundary + "\";start-info=\"" + startInfo + "\"",
332
multipart.getContentType() );
335
void SoapTest::parseMultipartTest( )
337
string rootCid = "root-cid";
338
string rootType = "text/plain";
339
string rootContent = "Some content";
341
string part2Cid = "part2-cid";
342
string part2Type = "application/octet-stream";
343
string part2Content = "Some content 2";
345
string startInfo = "some info";
347
string boundary = "------------ABCDEF-Boundary";
348
string body = "\r\n--" + boundary + "\r\n" +
349
"Content-Id: <" + rootCid + ">\r\n" +
350
"Content-Type: " + rootType + "\r\n" +
351
"Content-Transfer-Encoding: binary\r\n" +
354
"\r\n--" + boundary + "\r\n" +
355
// Voluntarily make a case-sensitivity error to test the SharePoint case
356
"Content-ID: <" + part2Cid + ">\r\n" +
357
"Content-Type: " + part2Type + "\r\n" +
358
"Content-Transfer-Encoding: binary\r\n" +
361
"\r\n--" + boundary + "--\r\n";
363
// Added a space before one of the items as it may happen
364
string contentType = "multipart/related; start=\"" + rootCid + "\";type=\"" + rootType + "\";" +
365
"boundary=\"" + boundary + "\";start-info=\"" + startInfo + "\"";
367
RelatedMultipart multipart( body, contentType );
369
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong start Content id", rootCid, multipart.getStartId( ) );
370
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong start info", startInfo, multipart.getStartInfo( ) );
371
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong boundary", boundary, multipart.getBoundary( ) );
373
vector< string > cids = multipart.getIds( );
374
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong number of parts parsed", size_t( 2 ), cids.size( ) );
376
RelatedPartPtr actualRoot = multipart.getPart( rootCid );
377
CPPUNIT_ASSERT_MESSAGE( "No part corresponding to root cid", actualRoot.get( ) != NULL );
378
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong root part content type", rootType, actualRoot->getContentType( ) );
379
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong root part content", rootContent, actualRoot->getContent( ) );
381
RelatedPartPtr actualPart2 = multipart.getPart( part2Cid );
382
CPPUNIT_ASSERT_MESSAGE( "No part corresponding to part2 cid", actualPart2.get( ) != NULL );
383
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong part2 part content type", part2Type, actualPart2->getContentType( ) );
384
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Wrong part2 part content", part2Content, actualPart2->getContent( ) );
387
void SoapTest::getStreamFromNodeXopTest( )
389
// Create the test multipart
390
string dataCid = "http://data-cid";
391
string dataCidEncoded = "http%3A%2F%2Fdata-cid";
392
string dataContent = "Some transfered content";
394
string boundary = "------------ABCDEF-Boundary";
395
string body = "\r\n--" + boundary + "\r\n" +
396
"Content-Id: <root-cid>\r\n" +
397
"Content-Type: text/plain\r\n" +
398
"Content-Transfer-Encoding: binary\r\n" +
400
"Who cares? we assume, this has been properly extracted in this test" +
401
"\r\n--" + boundary + "\r\n" +
402
"Content-Id: " + dataCid + "\r\n" +
403
"Content-Type: text/plain\r\n" +
404
"Content-Transfer-Encoding: binary\r\n" +
407
"\r\n--" + boundary + "--\r\n";
409
string contentType = string( "multipart/related;start=\"root-cid\";type=\"text/plain\";" ) +
410
"boundary=\"" + boundary + "\";start-info=\"info\"";
412
RelatedMultipart multipart( body, contentType );
417
<< " <xop:Include xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href=\"cid:" << dataCidEncoded << "\"/>"
419
xmlNodePtr node = test::getXmlNode( buf.str( ) );
421
// Run the tested method
422
boost::shared_ptr< istream > stream = getStreamFromNode( node, multipart );
426
out << stream->rdbuf( );
427
CPPUNIT_ASSERT_EQUAL( dataContent, out.str( ) );
430
void SoapTest::getStreamFromNodeBase64Test( )
432
// Create the test multipart
433
string boundary = "------------ABCDEF-Boundary";
434
string body = "\r\n--" + boundary + "\r\n" +
435
"Content-Id: <root-cid>\r\n" +
436
"Content-Type: text/plain\r\n" +
437
"Content-Transfer-Encoding: binary\r\n" +
439
"Who cares? we assume, this has been properly extracted in this test" +
440
"\r\n--" + boundary + "--\r\n";
442
string contentType = string( "multipart/related;start=\"root-cid\";type=\"text/plain\";" ) +
443
"boundary=\"" + boundary + "\";start-info=\"info\"";
445
RelatedMultipart multipart( body, contentType );
448
string dataContent = "U29tZSB0cmFuc2ZlcmVkIGNvbnRlbnQ=";
449
string expectedContent = "Some transfered content";
452
buf << "<stream>" << dataContent << "</stream>";
453
xmlNodePtr node = test::getXmlNode( buf.str( ) );
455
// Run the tested method
456
boost::shared_ptr< istream > stream = getStreamFromNode( node, multipart );
460
out << stream->rdbuf( );
461
CPPUNIT_ASSERT_EQUAL( expectedContent, out.str( ) );
464
void SoapTest::writeCmismStreamTest( )
466
// Initialize the writer
467
xmlBufferPtr buf = xmlBufferCreate( );
468
xmlTextWriterPtr writer = xmlNewTextWriterMemory( buf, 0 );
469
xmlTextWriterStartDocument( writer, NULL, NULL, NULL );
471
// Test writeCmismStream
472
RelatedMultipart multipart;
473
string contentType( "text/plain" );
474
string content( "Expected content" );
475
string filename( "name.txt" );
476
boost::shared_ptr< ostream > os( new stringstream( content ) );
477
writeCmismStream( writer, multipart, os, contentType, filename );
479
// Close the writer and check the results
480
xmlTextWriterEndDocument( writer );
481
string str( ( const char * )xmlBufferContent( buf ) );
483
vector< string > ids = multipart.getIds( );
484
CPPUNIT_ASSERT_EQUAL( size_t( 1 ), ids.size( ) );
485
string partId = ids.front( );
487
RelatedPartPtr part = multipart.getPart( partId );
488
CPPUNIT_ASSERT_MESSAGE( "Missing stream related part", part.get( ) != NULL );
489
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Content not properly attached", content, part->getContent( ) );
491
stringstream expectedXml;
492
expectedXml << "<?xml version=\"1.0\"?>\n"
493
<< "<cmism:length>" << content.size( ) << "</cmism:length>"
494
<< "<cmism:mimeType>" << contentType << "</cmism:mimeType>"
495
<< "<cmism:filename>" << filename << "</cmism:filename>"
497
<< "<xop:Include xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href=\"cid:" << partId << "\"/>"
498
<< "</cmism:stream>\n";
499
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Envelope part isn't correct", expectedXml.str( ), str );
502
xmlFreeTextWriter( writer );
503
xmlBufferFree( buf );