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