/*- * ============LICENSE_START======================================================= * ECOMP-TEST * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= */ package org.openecomp.policy.pdp.test.std.json; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.junit.Test; import com.att.research.xacml.api.Advice; import com.att.research.xacml.api.Attribute; import com.att.research.xacml.api.AttributeCategory; import com.att.research.xacml.api.IdReference; import com.att.research.xacml.api.Obligation; import com.att.research.xacml.api.Response; import com.att.research.xacml.api.Result; import com.att.research.xacml.std.dom.DOMResponse; import com.att.research.xacml.std.json.JSONResponse; import com.att.research.xacml.util.ListUtil; /** * Test JSON Response convert to object - Conformance tests * * TO RUN - use jUnit * In Eclipse select this file or the enclosing directory, right-click and select Run As/JUnit Test * * Note: some of the validation tests comparing the XML-derived Results to the JSON-derived Results are high-level comparisons of Collections. * When this class was first created that was sufficient to pass all Conformance tests. * However if this sees a failure in a Conformance test, those validations may need to be upgraded to look at the individual data elements to see what is wrong. * * */ public class ResponseConformanceTest { // where to find the conformance test XML files private final String CONFORMANCE_DIRECTORY_PATH = "testsets/conformance/xacml3.0-ct-v.0.4"; // The request object output from each test conversion from JSON string Response response; // test just one of each top-level element. // For simple elements also test for incorrect type @Test public void testConformanceResponses() { List filesInDirectory = null; File conformanceDirectory = null; File currentFile = null; try { conformanceDirectory = new File(CONFORMANCE_DIRECTORY_PATH); filesInDirectory = getRequestsInDirectory(conformanceDirectory); } catch (Exception e) { fail("Unable to set up Conformance tests for dir '" + conformanceDirectory.getAbsolutePath()+"' e="+ e); } // run through each XML file // - load the file from XML into an internal Response object // - generate the JSON representation of that Response object // - load that JSON representation into a new Response object // - compare the 2 Request objects Response xmlResponse = null; Response jsonResponse = null; try { for (File f : filesInDirectory) { currentFile = f; //// This is a simple way to select just one file for debugging - comment out when not being used //if ( ! f.getName().equals("IIIA030Response.xml") && ! f.getName().equals("IIIA330Response.xml")) { continue; } // during debugging it is helpful to know what file it is starting to work on // System.out.println("starting file="+currentFile.getName()); try { // load XML into a Response object xmlResponse = DOMResponse.load(f); } catch (Exception e) { // if XML does not load, just note it and continue with next file System.out.println("XML file did not load: '" + f.getName() + " e=" + e); continue; } // some tests have JSON response files to load, most do not String jsonFileName = f.getName().replace(".xml", ".json"); File jsonFile = new File(conformanceDirectory, jsonFileName); if (jsonFile.exists()) { //System.out.println("found file "+jsonFile.getName()); // json version exists in file, so load it jsonResponse = JSONResponse.load(jsonFile); } else { // json does not exist in file, so create it from the XML response using a String intermediate version String jsonResponseString = JSONResponse.toString(xmlResponse, false); //System.out.println(jsonResponseString); //System.out.println(JSONResponse.toString(xmlResponse, true)); jsonResponse = JSONResponse.load(jsonResponseString); } //System.out.println(JSONResponse.toString(xmlResponse, true)); // compare the two Response objects // compare results assertEquals(xmlResponse.getResults().size(), jsonResponse.getResults().size()); if (xmlResponse.getResults().size() == 0) { fail("neither XML nor JSON response have any Results"); } // Results are an un-ordered Collection. // There is no identifying information that is unique to a specific Result. // If there are more than one we cannot be sure which one corresponds with which. // The best we can do is say that one or more in the first list do not match any in the second list if (xmlResponse.getResults().size() > 1) { for (Result xmlResult : xmlResponse.getResults()) { boolean found = false; for (Result jsonResult : jsonResponse.getResults()) { if (xmlResult.equals(jsonResult)) { found = true; break; } } if (found) { continue; } // no match found System.out.println("No match for XML in " + f.getName()); System.out.println("XML =" + xmlResult.toString()); for (Result jsonResult : jsonResponse.getResults()) { System.out.println("JSON="+ jsonResult.toString()); } fail("JSON Response has no match for XML Result: " + xmlResult.toString()); } // we've done the best we can for multiple decisions, so go to next file continue; } // single Result in each Result xmlResult = xmlResponse.getResults().iterator().next(); Result jsonResult = jsonResponse.getResults().iterator().next(); // The following sections have not given us trouble, so checking is very high-level. // If we see a problem in one of these elements, the single line will need to be replaced with detailed examination of the objects. assertEquals(f.getName() + " Decision", xmlResult.getDecision(), jsonResult.getDecision()); assertEquals(f.getName() + " Status", xmlResult.getStatus(), jsonResult.getStatus()); // Obligations if (xmlResult.getObligations() != jsonResult.getObligations()) { Collection xmlObligations = xmlResult.getObligations(); Collection jsonObligations = jsonResult.getObligations(); // if both are null we do not get here if (xmlObligations == null || jsonObligations == null) { fail(f.getName() + " Obligations has null \nXML="+xmlObligations + "\nJSON="+jsonObligations); } if (ListUtil.equalsAllowNulls(xmlObligations, jsonObligations) == false) { // collections are not equal, so need to examine further fail(f.getName() + " Obligation collections not equal\nXML="+xmlObligations + "\nJSON="+jsonObligations); } } // AssociatedAdvice if (xmlResult.getAssociatedAdvice() != jsonResult.getAssociatedAdvice()) { Collection xmlAdvice = xmlResult.getAssociatedAdvice(); Collection jsonAdvice = jsonResult.getAssociatedAdvice(); // if both are null we do not get here if (xmlAdvice == null || jsonAdvice == null) { fail(f.getName() + " Advice has null \nXML="+xmlAdvice + "\nJSON="+jsonAdvice); } if (ListUtil.equalsAllowNulls(xmlAdvice, jsonAdvice) == false) { // collections are not equal, so need to examine further fail(f.getName() + " Advice collections not equal\nXML="+xmlAdvice + "\nJSON="+jsonAdvice); } } // check Attributes in more detail Collection xmlAttributes = xmlResult.getAttributes(); Collection jsonAttributes = jsonResult.getAttributes(); if (xmlAttributes == null && jsonAttributes != null || xmlAttributes != null && jsonAttributes == null) { fail(f.getName() + " XML Attributes="+xmlAttributes + " but JSON Attributes=" + jsonAttributes); } if (xmlAttributes != null) { // both are non-null if (xmlAttributes.size() != jsonAttributes.size()) { String xmlAttributesString = "XML categorys="; for (AttributeCategory ac : xmlAttributes) { xmlAttributesString += " " + ac.getCategory().stringValue(); } String jsonAttributesString = "JSON categorys="; for (AttributeCategory ac : jsonAttributes) { jsonAttributesString += " " + ac.getCategory().stringValue(); } fail(f.getName() + " XML and JSON have different number of Category elements: " + xmlAttributesString + ", " + jsonAttributesString); } // Attribute collections are the same size but may be in different orders. // for each XML category try to find the corresponding JSON category. // ASSUME that each category only shows up once!!!! for (AttributeCategory xmlAttributeCategory : xmlAttributes) { boolean attributeCategoryFound = false; for (AttributeCategory jsonAttributeCategory : jsonAttributes) { if (xmlAttributeCategory.equals(jsonAttributeCategory)) { attributeCategoryFound = true; break; } // not an exact match, but if same CategoryId then need to check individual Attribute objects if (xmlAttributeCategory.getCategory().equals(jsonAttributeCategory.getCategory())) { // same category if (xmlAttributeCategory.getAttributes().size() != jsonAttributeCategory.getAttributes().size()) { System.out.println("XML =" + xmlAttributeCategory.getAttributes()); System.out.println("JSON=" + jsonAttributeCategory.getAttributes()); fail(f.getName() + " Attributes Category '" + xmlAttributeCategory.getCategory().stringValue() + "' size mismatch; XML="+ xmlAttributeCategory.getAttributes().size() +", JSON=" + jsonAttributeCategory.getAttributes().size()); } for (Attribute xmlAttr : xmlAttributeCategory.getAttributes()) { boolean attributeFound = false; for (Attribute jsonAttr : jsonAttributeCategory.getAttributes()) { if (xmlAttr.equals(jsonAttr)) { attributeFound = true; break; } } if (attributeFound) { // check next XML attribute continue; } System.out.println("Attribute not found in JSON, Category="+xmlAttributeCategory.getCategory()); System.out.println("XML Attribute ="+ xmlAttr); System.out.println("JSON Attributes=" + jsonAttributeCategory.toString()); fail(f.getName() + " Attribute not found in JSON, Category=" + xmlAttributeCategory.getCategory() + "/nXML Attribute="+xmlAttr+ "\nJSON Category Attributes="+jsonAttributeCategory.toString()); } } } if (attributeCategoryFound) { continue; } fail("XML Category not found in JSON; xml="+xmlAttributeCategory.toString()); } } // PolicyIdentifiers if (xmlResult.getPolicyIdentifiers() != jsonResult.getPolicyIdentifiers()) { Collection xmlIdReferences = xmlResult.getPolicyIdentifiers(); Collection jsonIdReferences = jsonResult.getPolicyIdentifiers(); // if both are null we do not get here if (xmlIdReferences == null || jsonIdReferences == null) { fail(f.getName() + " PolicyIdentifiers has null \nXML="+xmlIdReferences + "\nJSON="+jsonIdReferences); } if (ListUtil.equalsAllowNulls(xmlIdReferences, jsonIdReferences) == false) { // collections are not equal, so need to examine further fail(f.getName() + " PolicyIdentifiers collections not equal\nXML="+xmlIdReferences+ "\nJSON="+jsonIdReferences); } } // PolicySetIdentifiers if (xmlResult.getPolicySetIdentifiers() != jsonResult.getPolicySetIdentifiers()) { Collection xmlIdReferences = xmlResult.getPolicySetIdentifiers(); Collection jsonIdReferences = jsonResult.getPolicySetIdentifiers(); // if both are null we do not get here if (xmlIdReferences == null || jsonIdReferences == null) { fail(f.getName() + " PolicySetIdentifiers has null \nXML="+xmlIdReferences + "\nJSON="+jsonIdReferences); } if (ListUtil.equalsAllowNulls(xmlIdReferences, jsonIdReferences) == false) { // collections are not equal, so need to examine further fail(f.getName() + " PolicySetIdentifiers collections not equal\nXML="+xmlIdReferences + "\nJSON="+jsonIdReferences); } } } } catch (Exception e) { fail ("Failed test with '" + currentFile.getName() + "', e=" + e); } } // // HELPER to get list of all Request files in the given directory // private List getRequestsInDirectory(File directory) { List fileList = new ArrayList(); File[] fileArray = directory.listFiles(); for (File f : fileArray) { if (f.isDirectory()) { List subDirList = getRequestsInDirectory(f); fileList.addAll(subDirList); } if (f.getName().endsWith("Response.xml")) { fileList.add(f); } } return fileList; } } /* * This is a place to copy the really long output from test rigs that need to be manually edited for readability.... {"Response":[{"Status":{"StatusCode":{"Value":"urn:oasis:names:tc:xacml:1.0:status:ok"}},"Obligations":[{"Id":"urn:oasis:names:tc:xacml:2.0:conformance-test:IIIA030:obligation-1","AttributeAssignment":[ {"Value":"assignment1","DataType":"string","AttributeId":"urn:oasis:names:tc:xacml:2.0:conformance-test:IIIA030:assignment1"}, {"Value":{"Namespaces":[{"Namespace":"urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"},{"Namespace":"http://www.w3.org/2001/XMLSchema-instance","Prefix":"xsi"}], "XPathCategory":"urn:oasis:names:tc:xacml:3.0:attribute-category:resource", "XPath":"//md:records/md:record"}, "DataType":"xpathExpression", "AttributeId":"urn:oasis:names:tc:xacml:2.0:conformance-test:IIIA030:assignment2"}]}],"Decision":"Permit"}]} */