https://issues.shibboleth.net/jira/browse/CPPOST-70
[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         assertEquals("Marshalled DOM was not the same as the expected DOM", expectedDOM, xmlObject, canMarshall);
109         // Test a clone operation before destroying the original.
110         xmlObject->releaseThisAndChildrenDOM();
111         delete xmlObject->clone();
112         delete xmlObject;
113     }
114
115     void assertEquals(const char* failMessage, const XMLCh* expectedString, const XMLCh* testString) {
116         char* buf = nullptr;
117         if (!XMLString::equals(expectedString, testString)) {
118             buf = XMLString::transcode(testString);
119             TS_TRACE(buf ? buf : "(NULL)");
120             XMLString::release(&buf);
121             buf = XMLString::transcode(expectedString);
122             TS_TRACE(buf ? buf : "(NULL)");
123             XMLString::release(&buf);
124             TSM_ASSERT(failMessage, false);
125         }
126     }
127
128 public:
129     void setUp() {
130         ParserPool& p=XMLToolingConfig::getConfig().getParser();
131         if (!singleElementFile.empty()) {
132             ifstream fs(singleElementFile.c_str());
133             expectedDOM = p.parse(fs);
134         }
135
136         if (!singleElementOptionalAttributesFile.empty()) {
137             ifstream fs(singleElementOptionalAttributesFile.c_str());
138             expectedOptionalAttributesDOM = p.parse(fs);
139         }
140
141         if (!childElementsFile.empty()) {
142             ifstream fs(childElementsFile.c_str());
143             expectedChildElementsDOM = p.parse(fs);
144         }
145     }
146     
147     void tearDown() {
148         if (expectedDOM) expectedDOM->release();
149         if (expectedOptionalAttributesDOM) expectedOptionalAttributesDOM->release();
150         if (expectedChildElementsDOM) expectedChildElementsDOM->release();
151     }
152 };
153
154 class SAMLObjectValidatorBaseTestCase : virtual public SAMLObjectBaseTestCase {
155
156     public:
157         SAMLObjectValidatorBaseTestCase() : target(nullptr), targetQName(nullptr), builder(nullptr), validator(nullptr) {}
158
159         virtual ~SAMLObjectValidatorBaseTestCase() {
160             delete validator;
161         }
162
163     protected: 
164         /** The primary XMLObject which will be the target of a given test run */
165         XMLObject* target;
166
167         /** QName of the object to be tested */
168         xmltooling::QName targetQName;
169
170         /** Builder for XMLObjects of type targetQName */
171         const XMLObjectBuilder* builder;
172
173         /** Validator for the type corresponding to the test target */
174         Validator* validator;
175
176         /** Subclasses should override to populate required elements and attributes */
177         virtual void populateRequiredData() { }
178
179         /**
180          * Asserts that the validation of default test XMLObject target 
181          * was successful, as expected.
182          * 
183          * @param message
184          */
185         void assertValidationPass(const char* message) {
186             assertValidationPass(message, target);
187         }
188
189         /**
190          * Asserts that the validation of the specified XMLObject target 
191          * was successful, as expected.
192          * 
193          * @param message
194          * @param validateTarget
195          */
196         void assertValidationPass(const char* message, XMLObject* validateTarget) {
197             try {
198                 validator->validate(validateTarget);
199             } catch (ValidationException &e) {
200                 TS_TRACE(message);
201                 TS_TRACE("Expected success, but validation failure raised following ValidationException: ");
202                 TS_FAIL(e.getMessage());
203             }
204         }
205
206         /**
207          * Asserts that the validation of the default test XMLObject target 
208          * failed, as expected.
209          * 
210          * @param message
211          */
212         void assertValidationFail(const char* message) {
213             assertValidationFail(message, target);
214         }
215
216         /**
217          * Asserts that the validation of the specified XMLObject target 
218          * failed, as expected.
219          * 
220          * @param message
221          * @param validateTarget
222          */
223         void assertValidationFail(const char* message, XMLObject* validateTarget) {
224             try {
225                 validator->validate(validateTarget);
226                 TS_TRACE(message);
227                 TS_FAIL("Validation success, expected failure to raise ValidationException");
228             } catch (ValidationException&) {
229             }
230         }
231
232         /**
233          * Build an XMLObject based on the specified QName
234          * 
235          * @param targetQName QName of the type of object to build
236          * @returns new XMLObject of type targetQName
237          */
238         XMLObject* buildXMLObject(xmltooling::QName &targetQName) {
239             // Create the builder on the first request only, for efficiency
240             if (builder == nullptr) {
241                 builder = XMLObjectBuilder::getBuilder(targetQName);
242                 TSM_ASSERT("Unable to retrieve builder for object QName: " + targetQName.toString(), builder!=nullptr);
243             }
244             return builder->buildObject(targetQName.getNamespaceURI(), targetQName.getLocalPart(), targetQName.getPrefix());
245
246         }
247
248     public:
249
250         void setUp() {
251             SAMLObjectBaseTestCase::setUp();
252
253             TSM_ASSERT("targetQName was empty", targetQName.hasLocalPart());
254
255             TSM_ASSERT("validator was null", validator!=nullptr);
256
257             target = buildXMLObject(targetQName);
258             TSM_ASSERT("XMLObject target was NULL", target!=nullptr);
259             populateRequiredData();
260         }
261
262         void tearDown() {
263             delete target;
264             target=nullptr;
265             SAMLObjectBaseTestCase::tearDown();
266         }
267
268 };
269