Bump lib version.
[shibboleth/cpp-opensaml.git] / samltest / internal.h
1 /*
2  *  Copyright 2001-2007 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifdef WIN32
18 # define _CRT_SECURE_NO_DEPRECATE 1
19 # define _CRT_NONSTDC_NO_DEPRECATE 1
20 #endif
21
22 #include <cxxtest/TestSuite.h>
23
24 #include <fstream>
25 #include <saml/exceptions.h>
26 #include <saml/util/SAMLConstants.h>
27 #include <xmltooling/XMLObject.h>
28 #include <xmltooling/XMLObjectBuilder.h>
29 #include <xmltooling/XMLToolingConfig.h>
30 #include <xmltooling/validation/Validator.h>
31
32 using namespace xmltooling;
33 using namespace xercesc;
34 using namespace std;
35
36 extern string data_path;
37
38 class SAMLObjectBaseTestCase
39 {
40 protected:
41     /** Location of file containing a single element with NO optional attributes */
42     string singleElementFile;
43
44     /** Location of file containing a single element with all optional attributes */
45     string singleElementOptionalAttributesFile;
46
47     /** Location of file containing a single element with child elements */
48     string childElementsFile;
49
50     /** The expected result of a marshalled single element with no optional attributes */
51     DOMDocument* expectedDOM;
52
53     /** The expected result of a marshalled single element with all optional attributes */
54     DOMDocument* expectedOptionalAttributesDOM;
55
56     /** The expected result of a marshalled single element with child elements */
57     DOMDocument* expectedChildElementsDOM;
58
59     /**
60      * Unmarshalls an element file into its SAML XMLObject.
61      * 
62      * @return the SAML XMLObject from the file
63      */
64     XMLObject* unmarshallElement(string elementFile) {
65         try {
66             ParserPool& p=XMLToolingConfig::getConfig().getParser();
67             ifstream fs(elementFile.c_str());
68             DOMDocument* doc = p.parse(fs);
69             const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement());
70             return b->buildFromDocument(doc);
71         }
72         catch (XMLToolingException& e) {
73             TS_TRACE(typeid(e).name());
74             TS_TRACE(e.what());
75             throw;
76         }
77     }
78
79     void assertEquals(const char* failMessage, DOMDocument* expectedDOM, XMLObject* xmlObject, bool canMarshall=true) {
80         DOMElement* generatedDOM = xmlObject->getDOM();
81         if (!generatedDOM) {
82             if (!canMarshall) {
83                 TSM_ASSERT("DOM not available", false);
84             }
85             else {
86                 generatedDOM = xmlObject->marshall();
87             }
88         }
89         if (!generatedDOM->isEqualNode(expectedDOM->getDocumentElement())) {
90             string buf;
91             XMLHelper::serialize(generatedDOM, buf);
92             TS_TRACE(buf.c_str());
93             buf.erase();
94             XMLHelper::serialize(expectedDOM->getDocumentElement(), buf);
95             TS_TRACE(buf.c_str());
96             TSM_ASSERT(failMessage, false);
97         }
98     }
99
100     void assertEquals(DOMDocument* expectedDOM, XMLObject* xmlObject, bool canMarshall=true) {
101         assertEquals("Marshalled DOM was not the same as the expected DOM", expectedDOM, xmlObject, canMarshall);
102         delete xmlObject;
103     }
104
105     void assertEquals(const char* failMessage, const XMLCh* expectedString, const XMLCh* testString) {
106         char* buf = NULL;
107         if (!XMLString::equals(expectedString, testString)) {
108             buf = XMLString::transcode(testString);
109             TS_TRACE(buf ? buf : "(NULL)");
110             XMLString::release(&buf);
111             buf = XMLString::transcode(expectedString);
112             TS_TRACE(buf ? buf : "(NULL)");
113             XMLString::release(&buf);
114             TSM_ASSERT(failMessage, false);
115         }
116     }
117
118 public:
119     void setUp() {
120         ParserPool& p=XMLToolingConfig::getConfig().getParser();
121         if (!singleElementFile.empty()) {
122             ifstream fs(singleElementFile.c_str());
123             expectedDOM = p.parse(fs);
124         }
125
126         if (!singleElementOptionalAttributesFile.empty()) {
127             ifstream fs(singleElementOptionalAttributesFile.c_str());
128             expectedOptionalAttributesDOM = p.parse(fs);
129         }
130
131         if (!childElementsFile.empty()) {
132             ifstream fs(childElementsFile.c_str());
133             expectedChildElementsDOM = p.parse(fs);
134         }
135     }
136     
137     void tearDown() {
138         if (expectedDOM) expectedDOM->release();
139         if (expectedOptionalAttributesDOM) expectedOptionalAttributesDOM->release();
140         if (expectedChildElementsDOM) expectedChildElementsDOM->release();
141     }
142 };
143
144 class SAMLObjectValidatorBaseTestCase : virtual public SAMLObjectBaseTestCase {
145
146     public:
147         SAMLObjectValidatorBaseTestCase() : target(NULL), targetQName(NULL), builder(NULL), validator(NULL) {}
148
149         virtual ~SAMLObjectValidatorBaseTestCase() {
150             delete validator;
151         }
152
153     protected: 
154         /** The primary XMLObject which will be the target of a given test run */
155         XMLObject* target;
156
157         /** QName of the object to be tested */
158         QName targetQName;
159
160         /** Builder for XMLObjects of type targetQName */
161         const XMLObjectBuilder* builder;
162
163         /** Validator for the type corresponding to the test target */
164         Validator* validator;
165
166         /** Subclasses should override to populate required elements and attributes */
167         virtual void populateRequiredData() { }
168
169         /**
170          * Asserts that the validation of default test XMLObject target 
171          * was successful, as expected.
172          * 
173          * @param message
174          */
175         void assertValidationPass(const char* message) {
176             assertValidationPass(message, target);
177         }
178
179         /**
180          * Asserts that the validation of the specified XMLObject target 
181          * was successful, as expected.
182          * 
183          * @param message
184          * @param validateTarget
185          */
186         void assertValidationPass(const char* message, XMLObject* validateTarget) {
187             try {
188                 validator->validate(validateTarget);
189             } catch (ValidationException &e) {
190                 TS_TRACE(message);
191                 TS_TRACE("Expected success, but validation failure raised following ValidationException: ");
192                 TS_FAIL(e.getMessage());
193             }
194         }
195
196         /**
197          * Asserts that the validation of the default test XMLObject target 
198          * failed, as expected.
199          * 
200          * @param message
201          */
202         void assertValidationFail(const char* message) {
203             assertValidationFail(message, target);
204         }
205
206         /**
207          * Asserts that the validation of the specified XMLObject target 
208          * failed, as expected.
209          * 
210          * @param message
211          * @param validateTarget
212          */
213         void assertValidationFail(const char* message, XMLObject* validateTarget) {
214             try {
215                 validator->validate(validateTarget);
216                 TS_TRACE(message);
217                 TS_FAIL("Validation success, expected failure to raise ValidationException");
218             } catch (ValidationException&) {
219             }
220         }
221
222         /**
223          * Build an XMLObject based on the specified QName
224          * 
225          * @param targetQName QName of the type of object to build
226          * @returns new XMLObject of type targetQName
227          */
228         XMLObject* buildXMLObject(QName &targetQName) {
229             // Create the builder on the first request only, for efficiency
230             if (builder == NULL) {
231                 builder = XMLObjectBuilder::getBuilder(targetQName);
232                 TSM_ASSERT("Unable to retrieve builder for object QName: " + targetQName.toString(), builder!=NULL);
233             }
234             return builder->buildObject(targetQName.getNamespaceURI(), targetQName.getLocalPart(), targetQName.getPrefix());
235
236         }
237
238     public:
239
240         void setUp() {
241             SAMLObjectBaseTestCase::setUp();
242
243             TSM_ASSERT("targetQName was empty", targetQName.hasLocalPart());
244
245             TSM_ASSERT("validator was null", validator!=NULL);
246
247             target = buildXMLObject(targetQName);
248             TSM_ASSERT("XMLObject target was NULL", target!=NULL);
249             populateRequiredData();
250         }
251
252         void tearDown() {
253             delete target;
254             target=NULL;
255             SAMLObjectBaseTestCase::tearDown();
256         }
257
258 };
259