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