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