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