[POLICY-73] replace openecomp for policy-engine
[policy/engine.git] / ONAP-PDP / src / test / java / org / onap / policy / pdp / test / FunctionDefinitionXPathTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PDP
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.pdp.test;
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertTrue;
26 import static org.junit.Assert.fail;
27
28 import java.io.BufferedWriter;
29 import java.io.File;
30 import java.io.FileWriter;
31 import java.math.BigInteger;
32 import java.util.ArrayList;
33 import java.util.Iterator;
34 import java.util.List;
35
36 import javax.xml.namespace.NamespaceContext;
37 import javax.xml.xpath.XPath;
38 import javax.xml.xpath.XPathFactory;
39
40 import org.junit.Test;
41
42 import com.att.research.xacml.api.Request;
43 import com.att.research.xacml.api.XACML3;
44 import com.att.research.xacml.std.IdentifierImpl;
45 import com.att.research.xacml.std.StdRequest;
46 import com.att.research.xacml.std.StdStatus;
47 import com.att.research.xacml.std.datatypes.DataTypes;
48 import com.att.research.xacml.std.datatypes.XPathExpressionWrapper;
49 import com.att.research.xacml.std.dom.DOMRequest;
50 import com.att.research.xacmlatt.pdp.policy.ExpressionResult;
51 import com.att.research.xacmlatt.pdp.policy.FunctionArgument;
52 import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue;
53 import com.att.research.xacmlatt.pdp.std.StdEvaluationContext;
54 import com.att.research.xacmlatt.pdp.std.StdFunctions;
55 import com.att.research.xacmlatt.pdp.std.functions.*;
56
57 /**
58  * Test of PDP Functions (See XACML core spec section A.3)
59  * 
60  * TO RUN - use jUnit
61  * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test
62  * 
63  *
64  */
65 public class FunctionDefinitionXPathTest {
66         
67         //
68         // Strings for the Request contents
69         //
70         
71         String reqStrMainStart = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" 
72                         + "<Request xsi:schemaLocation=\"urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" 
73                         + " http://docs.oasis-open.org/xacml/3.0/xacml-core-v3-schema-wd-17.xsd\"" 
74                         + " ReturnPolicyIdList=\"false\""
75                         + " CombinedDecision=\"false\""
76                         + " xmlns=\"urn:oasis:names:tc:xacml:3.0:core:schema:wd-17\""
77                         + " xmlns:md=\"http://www.medico.com/schemas/record\""
78                         + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
79                         + "     <Attributes Category=\"urn:oasis:names:tc:xacml:1.0:subject-category:access-subject\">"
80                         + "             <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:1.0:subject:subject-id\">"
81                         + "                     <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">Julius Hibbert</AttributeValue>"
82                         + "             </Attribute>"
83                         + "             <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:2.0:conformance-test:test-attr\">"
84                         + "                     <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">   This  is IT!  </AttributeValue>"
85                         + "             </Attribute>"
86                         + "             <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:2.0:conformance-test:test-attr\">"
87                         + "                     <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">   This  is IT!  </AttributeValue>"
88                         + "             </Attribute>"
89                         + "</Attributes>";
90               
91         String reqStrResourceStart =   "<Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:resource\">";
92
93         String reqStrContentMdRecord =
94                 " <Content>" +
95                         "<md:record>" +
96                 "<md:hospital_info>" +
97                    "<md:name>ABC Hospital</md:name>" +
98                     "<md:department>Surgery</md:department>" +
99                 "</md:hospital_info>" +
100                 "<md:patient_info>" +
101                     "<md:name>Bart Simpson</md:name>" +
102                     "<md:age>60</md:age>" +
103                     "<md:sex>male</md:sex>" +
104                     "<md:health_insurance>123456</md:health_insurance>" +
105                 "</md:patient_info>" +
106                 "<md:diagnosis_info>" +
107                     "<md:diagnosis>" +
108                         "<md:item type=\"primary\">Gastric Cancer</md:item>" +
109                         "<md:item type=\"secondary\">Hyper tension</md:item>" +
110                     "</md:diagnosis>" +
111                     "<md:pathological_diagnosis>" +
112                         "<md:diagnosis>" +
113                             "<md:item type=\"primary\">Well differentiated adeno carcinoma</md:item>" +
114                         "</md:diagnosis>" +
115                         "<md:date>2000-10-05</md:date>" +
116                         "<md:malignancy type=\"yes\"/>" +
117                     "</md:pathological_diagnosis>" +
118                 "</md:diagnosis_info>  " +             
119            " </md:record>" +
120          "</Content>";
121         String reqStrMalformedContent = 
122                         " <Content>" +
123                                         "<md:record>" +
124                                 "<md:hospital_info>" +
125                                    "<md:name>ABC Hospital</md:name>" +
126                                         "<md:malignancy type=\"yes\"/>" +
127                     "</Content>";
128         String reqStrResourceEnd = "    <Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:1.0:resource:resource-id\">"
129                         + "             <AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#anyURI\">http://medico.com/record/patient/BartSimpson</AttributeValue>"
130                         + "  </Attribute>"
131                         + "</Attributes> ";
132         String reqStrActionStart =   "<Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:action\">";
133
134         String reqStrActionEnd = "<Attribute IncludeInResult=\"false\" AttributeId=\"urn:oasis:names:tc:xacml:1.0:action:action-id\">"
135                         + "<AttributeValue DataType=\"http://www.w3.org/2001/XMLSchema#string\">read</AttributeValue>"
136                         + "</Attribute>"
137                         + "</Attributes> ";
138         String reqStrEnvironmentStartEnd = "  <Attributes Category=\"urn:oasis:names:tc:xacml:3.0:attribute-category:environment\" />";
139         String reqStrMainEnd = " </Request>";
140
141         
142         // combined strings for convenience
143         String reqStrMainResourceStart = reqStrMainStart + reqStrResourceStart;
144         String reqStrResourceAllEnd = reqStrResourceEnd + reqStrActionStart + reqStrActionEnd + reqStrEnvironmentStartEnd + reqStrMainEnd;
145         
146         
147         /*
148          * variables useful in the following tests
149          */
150         List<FunctionArgument> arguments = new ArrayList<FunctionArgument>();
151         
152         
153         
154         // Name Spaces used in the XML as part of these examples (copied from the Conformance tests) - needed for compiling XPaths
155         NamespaceContext nameSpaceContext = new NamespaceContext() {
156             @Override
157             public Iterator<?> getPrefixes(String arg0) { return null;}
158
159             @Override
160             public String getPrefix(String arg0) {return null;}
161
162             @Override
163             public String getNamespaceURI(String arg0) {
164                 if("md".equals(arg0)) {
165                     return "http://www.medico.com/schemas/record";
166                 } else if ("xacml-context".equals(arg0)) {
167                         return "urn:oasis:names:tc:xacml:3.0:context:schema:os";
168                 } else if ("xsi".equals(arg0)) {
169                         return "http://www.w3.org/2001/XMLSchema-instance";
170                 }
171                 return null;
172             }
173         };
174         
175         
176         
177         //
178         // XPath Function Attributes available for use in tests  (representing appropriate fragment of Policy)
179         //
180         
181         FunctionArgumentAttributeValue attrXnull = null;
182         FunctionArgumentAttributeValue attrXEmpty = null;
183         FunctionArgumentAttributeValue attrXNoCategory = null;
184         FunctionArgumentAttributeValue attrXNoValue = null;
185         FunctionArgumentAttributeValue attrXSlashSlashMdRecord = null;
186         FunctionArgumentAttributeValue attrXSlashSlashStar = null;
187         FunctionArgumentAttributeValue attrXSlashSlashMdName = null;
188         FunctionArgumentAttributeValue attrXSlashSlashMdMalignancy = null;
189         FunctionArgumentAttributeValue attrXNotInRequest = null;
190         FunctionArgumentAttributeValue attrXSlashSlashMdRecordSlashStar = null;
191         FunctionArgumentAttributeValue attrXMdPatientInfo = null;
192         
193         FunctionArgumentAttributeValue attrBadType = null;
194
195         // String version of attrs for use in Deprecated functions
196         FunctionArgumentAttributeValue attrStrnull = null;
197         FunctionArgumentAttributeValue attrStrEmpty = null;
198         FunctionArgumentAttributeValue attrStrNoCategory = null;
199         FunctionArgumentAttributeValue attrStrNoValue = null;
200         FunctionArgumentAttributeValue attrStrSlashSlashMdRecord = null;
201         FunctionArgumentAttributeValue attrStrSlashSlashStar = null;
202         FunctionArgumentAttributeValue attrStrSlashSlashMdName = null;
203         FunctionArgumentAttributeValue attrStrSlashSlashMdMalignancy = null;
204         FunctionArgumentAttributeValue attrStrNotInRequest = null;
205         FunctionArgumentAttributeValue attrStrSlashSlashMdRecordSlashStar = null;
206         FunctionArgumentAttributeValue attrStrMdPatientInfo = null;
207         
208         
209         //
210         // REQUEST objects available for use in tests
211         //
212         Request requestEmpty = new StdRequest(StdStatus.STATUS_OK);
213         Request requestMdRecord = null;
214         Request requestDoubleResources = null;
215         Request requestResourceActionContent = null;
216         Request requestContentInAction = null;
217
218
219         
220         
221         /**
222          * Set up all variables in one place because it is complicated (lots of steps needed for each attribute)
223          */
224         public FunctionDefinitionXPathTest() {
225                 try {
226                         XPathFactory xPathFactory = XPathFactory.newInstance();
227                         XPath xpath = xPathFactory.newXPath();
228                         xpath.setNamespaceContext(nameSpaceContext);
229                         
230                         // Create XPaths to use in expressions
231                         XPathExpressionWrapper xEmpty = new XPathExpressionWrapper("");
232                         XPathExpressionWrapper xSlashSlashMdRecord = new XPathExpressionWrapper(xpath.compile("//md:record"));
233                         XPathExpressionWrapper xSlashSlashStar = new XPathExpressionWrapper(xpath.compile("//*"));
234                         XPathExpressionWrapper xSlashSlashMdName = new XPathExpressionWrapper(xpath.compile("//md:name"));
235                         XPathExpressionWrapper xSlashSlashMdMalignancy = new XPathExpressionWrapper(xpath.compile("//md:malignancy"));
236                         XPathExpressionWrapper xNotInRequest = new XPathExpressionWrapper(xpath.compile("value_Not_in_request"));
237                         XPathExpressionWrapper xSlashSlashMdRecordSlashStar = new XPathExpressionWrapper(xpath.compile("//md:record/*"));
238                         XPathExpressionWrapper xMdPatientInfo = new XPathExpressionWrapper(xpath.compile("md:patient_info"));
239
240         
241                         
242                         // create Function Attributes out of the XPathExpressions
243                         attrXnull = new FunctionArgumentAttributeValue(null);
244                         attrXEmpty = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xEmpty));
245                         attrXNoCategory = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashMdRecord));
246                         attrXNoValue = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xEmpty,
247                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
248                         attrXSlashSlashMdRecord = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashMdRecord,
249                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
250                         attrXSlashSlashStar = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashStar,
251                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
252                         attrXSlashSlashMdName = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashMdName,
253                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
254                         attrXSlashSlashMdMalignancy = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashMdMalignancy,
255                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
256                         attrXNotInRequest = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xNotInRequest,
257                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
258                         
259                         attrXSlashSlashMdRecordSlashStar = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xSlashSlashMdRecordSlashStar,
260                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
261                         attrXMdPatientInfo = new FunctionArgumentAttributeValue(DataTypes.DT_XPATHEXPRESSION.createAttributeValue(xMdPatientInfo,
262                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));      
263                         
264                         
265                         // Deprecated versions of args
266                         attrStrnull = new FunctionArgumentAttributeValue(null);
267                         attrStrEmpty = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue(""));
268                         attrStrNoCategory = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//md:record"));
269                         attrStrNoValue = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("",
270                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
271                         attrStrSlashSlashMdRecord = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//md:record",
272                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
273                         attrStrSlashSlashStar = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//*",
274                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
275                         attrStrSlashSlashMdName = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//md:name",
276                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
277                         attrStrSlashSlashMdMalignancy = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//md:malignancy",
278                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
279                         attrStrNotInRequest = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("value_Not_in_request",
280                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
281                         
282                         attrStrSlashSlashMdRecordSlashStar = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("//md:record/*",
283                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));
284                         attrStrMdPatientInfo = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("md:patient_info",
285                                         new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource" )));      
286                         
287                         
288                         
289                         
290                         attrBadType = new FunctionArgumentAttributeValue(DataTypes.DT_STRING.createAttributeValue("some string"));
291                 
292                         
293                         
294                         // Request objects
295                         // to create a Request object the easiest way is to put the xml into a file and use the DOMRequest to load it.
296                         
297                         // single Content in the Resources section (normal valid request)
298                         String reqString = reqStrMainResourceStart + reqStrContentMdRecord + reqStrResourceAllEnd;
299                                 File tFile = File.createTempFile("functionJunit", "request");
300                                 BufferedWriter bw = new BufferedWriter(new FileWriter(tFile));
301                                 bw.append(reqString);
302                                 bw.flush();
303                                 bw.close();
304                         requestMdRecord = DOMRequest.load(tFile);
305                                 tFile.delete();
306                                 
307                         // Resources included twice
308                         reqString = reqStrMainResourceStart + reqStrContentMdRecord + reqStrResourceEnd + reqStrResourceStart + reqStrContentMdRecord +reqStrResourceAllEnd;
309                                 tFile = File.createTempFile("functionJunit", "request");
310                                 bw = new BufferedWriter(new FileWriter(tFile));
311                                 bw.append(reqString);
312                                 bw.flush();
313                                 bw.close();
314                         requestDoubleResources = DOMRequest.load(tFile);
315                                 tFile.delete();
316                                         
317                                 
318                         // content included in both Resource and Action - ok
319                         reqString = reqStrMainResourceStart + reqStrContentMdRecord + reqStrResourceEnd + reqStrActionStart + reqStrContentMdRecord + reqStrActionEnd + reqStrMainEnd;
320                                 tFile = File.createTempFile("functionJunit", "request");
321                                 bw = new BufferedWriter(new FileWriter(tFile));
322                                 bw.append(reqString);
323                                 bw.flush();
324                                 bw.close();     
325                         requestResourceActionContent = DOMRequest.load(tFile);
326                                 tFile.delete();
327                                 
328                         // Content included only in Action - missing content produces non-error result according to spec
329                         reqString = reqStrMainResourceStart + reqStrResourceEnd + reqStrActionStart + reqStrContentMdRecord + reqStrActionEnd + reqStrMainEnd;
330                                 tFile = File.createTempFile("functionJunit", "request");
331                                 bw = new BufferedWriter(new FileWriter(tFile));
332                                 bw.append(reqString);
333                                 bw.flush();
334                                 bw.close();             
335                         requestContentInAction = DOMRequest.load(tFile);
336                                 tFile.delete();
337                         
338                                 
339                                 
340                         // Test that Bad XML is caught
341                         @SuppressWarnings("unused")
342                         Request requestContentMisplaced = null;
343                         @SuppressWarnings("unused")
344                         Request requestMalformedContent = null;
345                         @SuppressWarnings("unused")
346                         Request requestDoubleContent = null;
347
348                         
349                         // Content included twice - error
350                         reqString = reqStrMainResourceStart + reqStrContentMdRecord + reqStrContentMdRecord +reqStrResourceAllEnd;
351                                 tFile = File.createTempFile("functionJunit", "request");
352                                 bw = new BufferedWriter(new FileWriter(tFile));
353                                 bw.append(reqString);
354                                 bw.flush();
355                                 bw.close();
356                         try {
357                                 requestDoubleContent = DOMRequest.load(tFile);
358                                         tFile.delete();
359                         } catch (com.att.research.xacml.std.dom.DOMStructureException e) {
360                                 // this is what it should do, so just continue
361                         } catch (Exception e) {
362                                 fail("Unexpected exception for bad XML, e="+e);
363                         }       
364                                 
365                         // Bad XML - Content not under a Category
366                         reqString = reqStrMainStart + reqStrContentMdRecord + reqStrResourceStart + reqStrResourceEnd + reqStrActionStart + reqStrActionEnd + reqStrMainEnd;
367                                 tFile = File.createTempFile("functionJunit", "request");
368                                 bw = new BufferedWriter(new FileWriter(tFile));
369                                 bw.append(reqString);
370                                 bw.flush();
371                                 bw.close();
372                         try {
373                                 requestContentMisplaced = DOMRequest.load(tFile);
374                                         tFile.delete();
375                         } catch (com.att.research.xacml.std.dom.DOMStructureException e) {
376                                 // this is what it should do, so just continue
377                         } catch (Exception e) {
378                                 fail("Unexpected exception for bad XML, e="+e);
379                         }
380                                 
381                         // Bad XML - Content is not valid XML
382                         reqString = reqStrMainResourceStart + reqStrMalformedContent + reqStrResourceAllEnd;
383                                 tFile = File.createTempFile("functionJunit", "request");
384                                 bw = new BufferedWriter(new FileWriter(tFile));
385                                 bw.append(reqString);
386                                 bw.flush();
387                                 bw.close();
388                         try {
389                                 requestMalformedContent = DOMRequest.load(tFile);
390                                         tFile.delete();
391                         } catch (com.att.research.xacml.std.dom.DOMStructureException e) {
392                                 // this is what it should do, so just continue
393                         } catch (Exception e) {
394                                 fail("Unexpected exception for bad XML, e="+e);
395                         }
396                         
397                 } catch (Exception e) {
398                         fail("Constructor initializing variables, e="+ e + "  cause="+e.getCause());
399                 }
400                 
401         }
402         
403
404         
405         
406         
407         
408         
409         
410         @Test
411         public void testXpath_node_count() {
412
413
414                 
415                 FunctionDefinitionXPath<?> fd = (FunctionDefinitionXPath<?>) StdFunctions.FD_XPATH_NODE_COUNT;
416                 
417                 // check identity and type of the thing created
418                 assertEquals(XACML3.ID_FUNCTION_XPATH_NODE_COUNT, fd.getId());
419                 assertEquals(DataTypes.DT_XPATHEXPRESSION.getId(), fd.getDataTypeArgs().getId());
420                 assertEquals(DataTypes.DT_INTEGER.getId(), fd.getDataTypeId());
421                 
422                 // just to be safe...  If tests take too long these can probably be eliminated
423                 assertFalse(fd.returnsBag());
424                 assertEquals(new Integer(1), fd.getNumArgs());
425                 
426
427                 // match all elements within context
428                 arguments.clear();
429                 arguments.add(attrXSlashSlashStar);
430                 ExpressionResult res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
431                 assertTrue(res.isOk());
432                 BigInteger resValue = (BigInteger)res.getValue().getValue();
433                 assertEquals(new BigInteger("18"), resValue);
434         
435                 // match exactly 1 element
436                 arguments.clear();
437                 arguments.add(attrXSlashSlashMdMalignancy);
438                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
439                 assertTrue(res.isOk());
440                 resValue = (BigInteger)res.getValue().getValue();
441                 assertEquals(new BigInteger("1"), resValue);
442                 
443                 // match a few but not all
444                 arguments.clear();
445                 arguments.add(attrXSlashSlashMdName);
446                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
447                 assertTrue(res.isOk());
448                 resValue = (BigInteger)res.getValue().getValue();
449                 assertEquals(new BigInteger("2"), resValue);
450                 
451                 
452                 // verify variables using in other tests: count nodes immediately under md:record
453                 arguments.clear();
454                 arguments.add(attrXSlashSlashMdRecordSlashStar);
455                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
456                 assertTrue(res.isOk());
457                 resValue = (BigInteger)res.getValue().getValue();
458                 assertEquals(new BigInteger("3"), resValue);
459                 
460                 // verify variables using in other tests: count number of records containing patient_info
461                 arguments.clear();
462                 arguments.add(attrXMdPatientInfo);
463                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
464                 assertTrue(res.isOk());
465                 resValue = (BigInteger)res.getValue().getValue();
466                 assertEquals(new BigInteger("1"), resValue);
467                 
468                 // verify variables using in other tests: count number of records containing md:name
469                 arguments.clear();
470                 arguments.add(attrXSlashSlashMdName);
471                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
472                 assertTrue(res.isOk());
473                 resValue = (BigInteger)res.getValue().getValue();
474                 assertEquals(new BigInteger("2"), resValue);
475                 
476                 // verify variables using in other tests: count number of records containing md:malignancy
477                 arguments.clear();
478                 arguments.add(attrXSlashSlashMdMalignancy);
479                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
480                 assertTrue(res.isOk());
481                 resValue = (BigInteger)res.getValue().getValue();
482                 assertEquals(new BigInteger("1"), resValue);
483                 
484                 
485                 
486                 
487                 // match no element
488                 arguments.clear();
489                 arguments.add(attrXNotInRequest);
490                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
491                 assertTrue(res.isOk());
492                 resValue = (BigInteger)res.getValue().getValue();
493                 assertEquals(new BigInteger("0"), resValue);
494                 
495                 // Resources included twice
496                 arguments.clear();
497                 arguments.add(attrXSlashSlashMdName);
498                 res = fd.evaluate(new StdEvaluationContext(requestDoubleResources, null, null), arguments);
499                 assertFalse(res.getStatus().isOk());
500                 assertEquals( "function:xpath-node-count More than one Content section for id 'urn:oasis:names:tc:xacml:3.0:attribute-category:resource'", res.getStatus().getStatusMessage());
501                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
502                 
503
504                 // Content in both Resource and Action categories (ok)
505                 arguments.clear();
506                 arguments.add(attrXSlashSlashMdName);
507                 res = fd.evaluate(new StdEvaluationContext(requestResourceActionContent, null, null), arguments);
508                 assertTrue(res.isOk());
509                 resValue = (BigInteger)res.getValue().getValue();
510                 assertEquals(new BigInteger("2"), resValue);
511
512                 // Content only in Action category (missing in Resources -> 0 according to spec)
513                 arguments.clear();
514                 arguments.add(attrXSlashSlashMdName);
515                 res = fd.evaluate(new StdEvaluationContext(requestContentInAction, null, null), arguments);
516                 assertTrue(res.isOk());
517                 resValue = (BigInteger)res.getValue().getValue();
518                 assertEquals(new BigInteger("0"), resValue);
519
520                 
521
522                 
523 //TODO - any other tests????
524                 
525                 // null Evaluation Context
526                 arguments.clear();
527                 arguments.add(attrXEmpty);
528                 res = fd.evaluate(null, arguments);
529                 assertFalse(res.getStatus().isOk());
530                 assertEquals( "function:xpath-node-count Got null EvaluationContext", res.getStatus().getStatusMessage());
531                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
532                 
533                 // null Request
534                 arguments.clear();
535                 arguments.add(attrXSlashSlashMdRecord);
536                 res = fd.evaluate(new StdEvaluationContext(null, null, null), arguments);
537                 assertFalse(res.getStatus().isOk());
538                 assertEquals( "function:xpath-node-count Got null Request in EvaluationContext", res.getStatus().getStatusMessage());
539                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
540                 
541                 // null attribute
542                 arguments.clear();
543                 arguments.add(attrXnull);
544                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
545                 assertFalse(res.getStatus().isOk());
546                 assertEquals( "function:xpath-node-count Got null attribute at arg index 0", res.getStatus().getStatusMessage());
547                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
548                 
549                 // no value
550                 arguments.clear();
551                 arguments.add(attrXNoValue);
552                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
553                 assertFalse(res.getStatus().isOk());
554                 assertEquals( "function:xpath-node-count XPathExpression returned null at index 0", res.getStatus().getStatusMessage());
555                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
556                 
557                 // no category
558                 arguments.clear();
559                 arguments.add(attrXNoCategory);
560                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
561                 assertFalse(res.getStatus().isOk());
562                 assertEquals( "function:xpath-node-count Got null Category at index 0", res.getStatus().getStatusMessage());
563                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
564                 
565
566                 // too many args
567                 arguments.clear();
568                 arguments.add(attrXEmpty);
569                 arguments.add(attrXEmpty);
570                 res = fd.evaluate(null, arguments);
571                 assertFalse(res.getStatus().isOk());
572                 assertEquals( "function:xpath-node-count Expected 1 arguments, got 2", res.getStatus().getStatusMessage());
573                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
574                 
575                 // too few args
576                 arguments.clear();
577                 res = fd.evaluate(null, arguments);
578                 assertFalse(res.getStatus().isOk());
579                 assertEquals( "function:xpath-node-count Expected 1 arguments, got 0", res.getStatus().getStatusMessage());
580                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
581                 
582                 // bad arg type
583                 arguments.clear();
584                 arguments.add(attrBadType);
585                 res = fd.evaluate(null, arguments);
586                 assertFalse(res.getStatus().isOk());
587                 assertEquals( "function:xpath-node-count Expected data type 'xpathExpression' saw 'string' at arg index 0", res.getStatus().getStatusMessage());
588                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
589                 
590                 // null args
591                 arguments.clear();
592                 arguments.add(null);
593                 res = fd.evaluate(null, arguments);
594                 assertFalse(res.getStatus().isOk());
595                 assertEquals( "function:xpath-node-count Got null argument at arg index 0", res.getStatus().getStatusMessage());
596                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
597                 
598         }
599
600         
601         @Test
602         public void testXpath_node_equal() {
603
604                 
605                 FunctionDefinitionXPath<?> fd = (FunctionDefinitionXPath<?>) StdFunctions.FD_XPATH_NODE_EQUAL;
606                 
607                 // check identity and type of the thing created
608                 assertEquals(XACML3.ID_FUNCTION_XPATH_NODE_EQUAL, fd.getId());
609                 assertEquals(DataTypes.DT_XPATHEXPRESSION.getId(), fd.getDataTypeArgs().getId());
610                 assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId());
611                 
612                 // just to be safe...  If tests take too long these can probably be eliminated
613                 assertFalse(fd.returnsBag());
614                 assertEquals(new Integer(2), fd.getNumArgs());
615                 
616                 
617                 // test normal success - exactly the same set
618                 arguments.clear();
619                 arguments.add(attrXSlashSlashMdName);
620                 arguments.add(attrXSlashSlashMdName);
621                 ExpressionResult res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
622                 assertTrue(res.isOk());
623                 Boolean resValue = (Boolean)res.getValue().getValue();
624                 assertTrue(resValue);
625                 
626                 // success - second list is subset of first list
627                 arguments.clear();
628                 arguments.add(attrXSlashSlashMdRecordSlashStar);
629                 arguments.add(attrXMdPatientInfo);
630                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
631                 assertTrue(res.isOk());
632                 resValue = (Boolean)res.getValue().getValue();
633                 assertTrue(resValue);
634                 
635                 // success - first list is subset of second list
636                 arguments.clear();
637                 arguments.add(attrXMdPatientInfo);
638                 arguments.add(attrXSlashSlashMdRecordSlashStar);
639                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
640                 assertTrue(res.isOk());
641                 resValue = (Boolean)res.getValue().getValue();
642                 assertTrue(resValue);
643                 
644                 // success - second list contains children of first list
645                 arguments.clear();
646                 arguments.add(attrXSlashSlashMdRecord);
647                 arguments.add(attrXSlashSlashMdName);
648                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
649                 assertTrue(res.isOk());
650                 resValue = (Boolean)res.getValue().getValue();
651                 assertFalse(resValue);
652                 
653                 // success - first list contains children of second list
654                 arguments.clear();
655                 arguments.add(attrXSlashSlashMdName);
656                 arguments.add(attrXSlashSlashMdRecord);
657                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
658                 assertTrue(res.isOk());
659                 resValue = (Boolean)res.getValue().getValue();
660                 assertFalse(resValue);
661                 
662
663                 
664                 // two non-overlapping sets
665                 arguments.clear();
666                 arguments.add(attrXSlashSlashMdMalignancy);
667                 arguments.add(attrXSlashSlashMdName);
668                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
669                 assertTrue(res.isOk());
670                 resValue = (Boolean)res.getValue().getValue();
671                 assertFalse(resValue);
672                 
673                 // first list contains nothing
674                 arguments.clear();
675                 arguments.add(attrXNotInRequest);
676                 arguments.add(attrXSlashSlashMdName);
677                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
678                 assertTrue(res.isOk());
679                 resValue = (Boolean)res.getValue().getValue();
680                 assertFalse(resValue);
681                 
682                 // second list contains nothing
683                 arguments.clear();
684                 arguments.add(attrXSlashSlashMdName);
685                 arguments.add(attrXNotInRequest);
686                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
687                 assertTrue(res.isOk());
688                 resValue = (Boolean)res.getValue().getValue();
689                 assertFalse(resValue);          
690                 
691                 
692                 
693 //TODO  
694                 //?????
695                 ///??????? add real tests
696                 //////
697                 
698                 
699                 // Resources included twice
700                 arguments.clear();
701                 arguments.add(attrXSlashSlashMdName);
702                 arguments.add(attrXSlashSlashMdName);
703                 res = fd.evaluate(new StdEvaluationContext(requestDoubleResources, null, null), arguments);
704                 assertFalse(res.getStatus().isOk());
705                 assertEquals( "function:xpath-node-equal More than one Content section for id 'urn:oasis:names:tc:xacml:3.0:attribute-category:resource'", res.getStatus().getStatusMessage());
706                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
707                 
708                 
709
710                 // Content in both Resource and Action categories (ok)
711                 arguments.clear();
712                 arguments.add(attrXSlashSlashMdName);
713                 arguments.add(attrXSlashSlashMdName);
714                 res = fd.evaluate(new StdEvaluationContext(requestResourceActionContent, null, null), arguments);
715                 assertTrue(res.isOk());
716                 resValue = (Boolean)res.getValue().getValue();
717                 assertTrue(resValue);
718
719                 // Content only in Action category (missing in Resources -> 0 according to spec)
720                 arguments.clear();
721                 arguments.add(attrXSlashSlashMdName);
722                 arguments.add(attrXSlashSlashMdName);
723                 res = fd.evaluate(new StdEvaluationContext(requestContentInAction, null, null), arguments);
724                 assertTrue(res.isOk());
725                 resValue = (Boolean)res.getValue().getValue();
726                 assertFalse(resValue);
727                 
728                 
729                 // null Evaluation Context
730                 arguments.clear();
731                 arguments.add(attrXSlashSlashMdRecord);
732                 arguments.add(attrXSlashSlashMdRecord);
733                 res = fd.evaluate(null, arguments);
734                 assertFalse(res.getStatus().isOk());
735                 assertEquals( "function:xpath-node-equal Got null EvaluationContext", res.getStatus().getStatusMessage());
736                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
737                 
738                 // null Request
739                 arguments.clear();
740                 arguments.add(attrXSlashSlashMdRecord);
741                 arguments.add(attrXSlashSlashMdRecord);
742                 res = fd.evaluate(new StdEvaluationContext(null, null, null), arguments);
743                 assertFalse(res.getStatus().isOk());
744                 assertEquals( "function:xpath-node-equal Got null Request in EvaluationContext", res.getStatus().getStatusMessage());
745                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
746                 
747                 // null attribute
748                 arguments.clear();
749                 arguments.add(attrXnull);
750                 arguments.add(attrXSlashSlashMdRecord);
751                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
752                 assertFalse(res.getStatus().isOk());
753                 assertEquals( "function:xpath-node-equal Got null attribute at arg index 0", res.getStatus().getStatusMessage());
754                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
755                 
756                 arguments.clear();
757                 arguments.add(attrXSlashSlashMdRecord);
758                 arguments.add(attrXnull);
759                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
760                 assertFalse(res.getStatus().isOk());
761                 assertEquals( "function:xpath-node-equal Got null attribute at arg index 1", res.getStatus().getStatusMessage());
762                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
763                 
764                 // no value
765                 arguments.clear();
766                 arguments.add(attrXNoValue);
767                 arguments.add(attrXSlashSlashMdRecord);
768                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
769                 assertFalse(res.getStatus().isOk());
770                 assertEquals( "function:xpath-node-equal XPathExpression returned null at index 0", res.getStatus().getStatusMessage());
771                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
772                 
773                 arguments.clear();
774                 arguments.add(attrXSlashSlashMdRecord);
775                 arguments.add(attrXNoValue);
776                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
777                 assertFalse(res.getStatus().isOk());
778                 assertEquals( "function:xpath-node-equal XPathExpression returned null at index 0", res.getStatus().getStatusMessage());
779                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
780                 
781                 // no category
782                 arguments.clear();
783                 arguments.add(attrXNoCategory);
784                 arguments.add(attrXSlashSlashMdRecord);
785                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
786                 assertFalse(res.getStatus().isOk());
787                 assertEquals( "function:xpath-node-equal Got null Category at index 0", res.getStatus().getStatusMessage());
788                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
789                 
790                 arguments.clear();
791                 arguments.add(attrXSlashSlashMdRecord);
792                 arguments.add(attrXNoCategory);
793                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
794                 assertFalse(res.getStatus().isOk());
795                 assertEquals( "function:xpath-node-equal XPathExpression returned null at index 0", res.getStatus().getStatusMessage());
796                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
797                 
798                 // too many args
799                 arguments.clear();
800                 arguments.add(attrXEmpty);
801                 arguments.add(attrXEmpty);
802                 arguments.add(attrXEmpty);
803                 res = fd.evaluate(null, arguments);
804                 assertFalse(res.getStatus().isOk());
805                 assertEquals( "function:xpath-node-equal Expected 2 arguments, got 3", res.getStatus().getStatusMessage());
806                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
807                 
808                 // too few args
809                 arguments.clear();
810                 res = fd.evaluate(null, arguments);
811                 assertFalse(res.getStatus().isOk());
812                 assertEquals( "function:xpath-node-equal Expected 2 arguments, got 0", res.getStatus().getStatusMessage());
813                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
814                 
815                 arguments.clear();
816                 arguments.add(attrXEmpty);
817                 res = fd.evaluate(null, arguments);
818                 assertFalse(res.getStatus().isOk());
819                 assertEquals( "function:xpath-node-equal Expected 2 arguments, got 1", res.getStatus().getStatusMessage());
820                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
821                         
822                 // bad arg type
823                 arguments.clear();
824                 arguments.add(attrBadType);
825                 arguments.add(attrXEmpty);
826                 res = fd.evaluate(null, arguments);
827                 assertFalse(res.getStatus().isOk());
828                 assertEquals( "function:xpath-node-equal Expected data type 'xpathExpression' saw 'string' at arg index 0", res.getStatus().getStatusMessage());
829                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
830                 
831                 arguments.clear();
832                 arguments.add(attrXEmpty);
833                 arguments.add(attrBadType);
834                 res = fd.evaluate(null, arguments);
835                 assertFalse(res.getStatus().isOk());
836                 assertEquals( "function:xpath-node-equal Expected data type 'xpathExpression' saw 'string' at arg index 1", res.getStatus().getStatusMessage());
837                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
838                 
839                 // null args
840                 arguments.clear();
841                 arguments.add(attrXEmpty);
842                 arguments.add(null);
843                 res = fd.evaluate(null, arguments);
844                 assertFalse(res.getStatus().isOk());
845                 assertEquals( "function:xpath-node-equal Got null argument at arg index 1", res.getStatus().getStatusMessage());
846                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
847                 
848                 arguments.clear();
849                 arguments.add(null);
850                 arguments.add(attrXEmpty);
851                 res = fd.evaluate(null, arguments);
852                 assertFalse(res.getStatus().isOk());
853                 assertEquals( "function:xpath-node-equal Got null argument at arg index 0", res.getStatus().getStatusMessage());
854                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
855                 
856         }
857         
858         
859         
860         
861         @Test
862         public void testXpath_node_match() {
863
864                 
865                 FunctionDefinitionXPath<?> fd = (FunctionDefinitionXPath<?>) StdFunctions.FD_XPATH_NODE_MATCH;
866                 
867                 // check identity and type of the thing created
868                 assertEquals(XACML3.ID_FUNCTION_XPATH_NODE_MATCH, fd.getId());
869                 assertEquals(DataTypes.DT_XPATHEXPRESSION.getId(), fd.getDataTypeArgs().getId());
870                 assertEquals(DataTypes.DT_BOOLEAN.getId(), fd.getDataTypeId());
871                 
872                 // just to be safe...  If tests take too long these can probably be eliminated
873                 assertFalse(fd.returnsBag());
874                 assertEquals(new Integer(2), fd.getNumArgs());
875                 
876                 
877                 // test normal success - exactly the same set
878                 arguments.clear();
879                 arguments.add(attrXSlashSlashMdName);
880                 arguments.add(attrXSlashSlashMdName);
881                 ExpressionResult res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
882                 assertTrue(res.isOk());
883                 Boolean resValue = (Boolean)res.getValue().getValue();
884                 assertTrue(resValue);
885                 
886                 // success - second list is subset of first list
887                 arguments.clear();
888                 arguments.add(attrXSlashSlashMdRecordSlashStar);
889                 arguments.add(attrXMdPatientInfo);
890                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
891                 assertTrue(res.isOk());
892                 resValue = (Boolean)res.getValue().getValue();
893                 assertTrue(resValue);
894                 
895                 // success - first list is subset of second list
896                 arguments.clear();
897                 arguments.add(attrXMdPatientInfo);
898                 arguments.add(attrXSlashSlashMdRecordSlashStar);
899                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
900                 assertTrue(res.isOk());
901                 resValue = (Boolean)res.getValue().getValue();
902                 assertTrue(resValue);
903                 
904                 // success - second list contains children of first list
905                 arguments.clear();
906                 arguments.add(attrXSlashSlashMdRecord);
907                 arguments.add(attrXSlashSlashMdName);
908                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
909                 assertTrue(res.isOk());
910                 resValue = (Boolean)res.getValue().getValue();
911                 assertTrue(resValue);
912                 
913                 // success - first list contains children of second list
914                 arguments.clear();
915                 arguments.add(attrXSlashSlashMdName);
916                 arguments.add(attrXSlashSlashMdRecord);
917                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
918                 assertTrue(res.isOk());
919                 resValue = (Boolean)res.getValue().getValue();
920                 assertFalse(resValue);
921                 
922                 
923                 
924                 // two non-overlapping sets
925                 arguments.clear();
926                 arguments.add(attrXSlashSlashMdMalignancy);
927                 arguments.add(attrXSlashSlashMdName);
928                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
929                 assertTrue(res.isOk());
930                 resValue = (Boolean)res.getValue().getValue();
931                 assertFalse(resValue);
932                 
933                 // first list contains nothing
934                 arguments.clear();
935                 arguments.add(attrXNotInRequest);
936                 arguments.add(attrXSlashSlashMdName);
937                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
938                 assertTrue(res.isOk());
939                 resValue = (Boolean)res.getValue().getValue();
940                 assertFalse(resValue);
941                 
942                 // second list contains nothing
943                 arguments.clear();
944                 arguments.add(attrXSlashSlashMdName);
945                 arguments.add(attrXNotInRequest);
946                 res = fd.evaluate(new StdEvaluationContext(requestMdRecord, null, null), arguments);
947                 assertTrue(res.isOk());
948                 resValue = (Boolean)res.getValue().getValue();
949                 assertFalse(resValue);  
950                 
951 //TODO          
952                 //?????
953                 ///??????? add real tests
954                 //////
955                 
956                 
957                 // Resources included twice
958                 arguments.clear();
959                 arguments.add(attrXSlashSlashMdName);
960                 arguments.add(attrXSlashSlashMdName);
961                 res = fd.evaluate(new StdEvaluationContext(requestDoubleResources, null, null), arguments);
962                 assertFalse(res.getStatus().isOk());
963                 assertEquals( "function:xpath-node-match More than one Content section for id 'urn:oasis:names:tc:xacml:3.0:attribute-category:resource'", res.getStatus().getStatusMessage());
964                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
965                 
966
967                 // Content in both Resource and Action categories (ok)
968                 arguments.clear();
969                 arguments.add(attrXSlashSlashMdName);
970                 arguments.add(attrXSlashSlashMdName);
971                 res = fd.evaluate(new StdEvaluationContext(requestResourceActionContent, null, null), arguments);
972                 assertTrue(res.isOk());
973                 resValue = (Boolean)res.getValue().getValue();
974                 assertTrue(resValue);
975
976                 // Content only in Action category (missing in Resources -> 0 according to spec)
977                 arguments.clear();
978                 arguments.add(attrXSlashSlashMdName);
979                 arguments.add(attrXSlashSlashMdName);
980                 res = fd.evaluate(new StdEvaluationContext(requestContentInAction, null, null), arguments);
981                 assertTrue(res.isOk());
982                 resValue = (Boolean)res.getValue().getValue();
983                 assertFalse(resValue);
984                 
985                 
986                 // null Evaluation Context
987                 arguments.clear();
988                 arguments.add(attrXSlashSlashMdRecord);
989                 arguments.add(attrXSlashSlashMdRecord);
990                 res = fd.evaluate(null, arguments);
991                 assertFalse(res.getStatus().isOk());
992                 assertEquals( "function:xpath-node-match Got null EvaluationContext", res.getStatus().getStatusMessage());
993                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
994                 
995                 // null Request
996                 arguments.clear();
997                 arguments.add(attrXSlashSlashMdRecord);
998                 arguments.add(attrXSlashSlashMdRecord);
999                 res = fd.evaluate(new StdEvaluationContext(null, null, null), arguments);
1000                 assertFalse(res.getStatus().isOk());
1001                 assertEquals( "function:xpath-node-match Got null Request in EvaluationContext", res.getStatus().getStatusMessage());
1002                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1003                 
1004                 // null attribute
1005                 arguments.clear();
1006                 arguments.add(attrXnull);
1007                 arguments.add(attrXSlashSlashMdRecord);
1008                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
1009                 assertFalse(res.getStatus().isOk());
1010                 assertEquals( "function:xpath-node-match Got null attribute at arg index 0", res.getStatus().getStatusMessage());
1011                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1012                 
1013                 arguments.clear();
1014                 arguments.add(attrXSlashSlashMdRecord);
1015                 arguments.add(attrXnull);
1016                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
1017                 assertFalse(res.getStatus().isOk());
1018                 assertEquals( "function:xpath-node-match Got null attribute at arg index 1", res.getStatus().getStatusMessage());
1019                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1020                 
1021                 // no value
1022                 arguments.clear();
1023                 arguments.add(attrXNoValue);
1024                 arguments.add(attrXSlashSlashMdRecord);
1025                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
1026                 assertFalse(res.getStatus().isOk());
1027                 assertEquals( "function:xpath-node-match XPathExpression returned null at index 0", res.getStatus().getStatusMessage());
1028                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1029                 
1030                 arguments.clear();
1031                 arguments.add(attrXSlashSlashMdRecord);
1032                 arguments.add(attrXNoValue);
1033                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
1034                 assertFalse(res.getStatus().isOk());
1035                 assertEquals( "function:xpath-node-match XPathExpression returned null at index 0", res.getStatus().getStatusMessage());
1036                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1037                 
1038                 // no category
1039                 arguments.clear();
1040                 arguments.add(attrXNoCategory);
1041                 arguments.add(attrXSlashSlashMdRecord);
1042                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
1043                 assertFalse(res.getStatus().isOk());
1044                 assertEquals( "function:xpath-node-match Got null Category at index 0", res.getStatus().getStatusMessage());
1045                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:syntax-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1046                 
1047                 arguments.clear();
1048                 arguments.add(attrXSlashSlashMdRecord);
1049                 arguments.add(attrXNoCategory);
1050                 res = fd.evaluate(new StdEvaluationContext(requestEmpty, null, null), arguments);
1051                 assertFalse(res.getStatus().isOk());
1052                 assertEquals( "function:xpath-node-match XPathExpression returned null at index 0", res.getStatus().getStatusMessage());
1053                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1054                 
1055                 // too many args
1056                 arguments.clear();
1057                 arguments.add(attrXEmpty);
1058                 arguments.add(attrXEmpty);
1059                 arguments.add(attrXEmpty);
1060                 res = fd.evaluate(null, arguments);
1061                 assertFalse(res.getStatus().isOk());
1062                 assertEquals( "function:xpath-node-match Expected 2 arguments, got 3", res.getStatus().getStatusMessage());
1063                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1064                 
1065                 // too few args
1066                 arguments.clear();
1067                 res = fd.evaluate(null, arguments);
1068                 assertFalse(res.getStatus().isOk());
1069                 assertEquals( "function:xpath-node-match Expected 2 arguments, got 0", res.getStatus().getStatusMessage());
1070                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1071                 
1072                 arguments.clear();
1073                 arguments.add(attrXEmpty);
1074                 res = fd.evaluate(null, arguments);
1075                 assertFalse(res.getStatus().isOk());
1076                 assertEquals( "function:xpath-node-match Expected 2 arguments, got 1", res.getStatus().getStatusMessage());
1077                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1078                         
1079                 // bad arg type
1080                 arguments.clear();
1081                 arguments.add(attrBadType);
1082                 arguments.add(attrXEmpty);
1083                 res = fd.evaluate(null, arguments);
1084                 assertFalse(res.getStatus().isOk());
1085                 assertEquals( "function:xpath-node-match Expected data type 'xpathExpression' saw 'string' at arg index 0", res.getStatus().getStatusMessage());
1086                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1087                 
1088                 arguments.clear();
1089                 arguments.add(attrXEmpty);
1090                 arguments.add(attrBadType);
1091                 res = fd.evaluate(null, arguments);
1092                 assertFalse(res.getStatus().isOk());
1093                 assertEquals( "function:xpath-node-match Expected data type 'xpathExpression' saw 'string' at arg index 1", res.getStatus().getStatusMessage());
1094                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1095                 
1096                 // null args
1097                 arguments.clear();
1098                 arguments.add(attrXEmpty);
1099                 arguments.add(null);
1100                 res = fd.evaluate(null, arguments);
1101                 assertFalse(res.getStatus().isOk());
1102                 assertEquals( "function:xpath-node-match Got null argument at arg index 1", res.getStatus().getStatusMessage());
1103                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1104                 
1105                 arguments.clear();
1106                 arguments.add(null);
1107                 arguments.add(attrXEmpty);
1108                 res = fd.evaluate(null, arguments);
1109                 assertFalse(res.getStatus().isOk());
1110                 assertEquals( "function:xpath-node-match Got null argument at arg index 0", res.getStatus().getStatusMessage());
1111                 assertEquals("urn:oasis:names:tc:xacml:1.0:status:processing-error", res.getStatus().getStatusCode().getStatusCodeValue().stringValue());
1112                 
1113                 
1114                 
1115         }
1116         
1117
1118         
1119         //
1120         // DEPRECATED versions that use String arguments rather than XPATHEXPRESSIONs
1121         // are NOT supported due to ambiguity in the semantics between 2.0 (<Request> is root and has only one <Content> in resources)
1122         //      and 3.0 (<Content> is root and there are multiple <Content> sections in any category)
1123         //
1124         
1125
1126         
1127 }