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