/*
* Copyright 2013, The Sporting Exchange Limited
* Copyright 2014, Simon Matić Langford
*
* 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.
*/
package com.betfair.testing.utils.cougar.assertions;
import com.betfair.testing.utils.cougar.misc.DataTypeEnum;
import com.betfair.testing.utils.cougar.misc.ObjectUtil;
import com.betfair.testing.utils.cougar.misc.XMLHelpers;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.xml.serializer.DOMSerializer;
import org.apache.xml.serializer.ToTextStream;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.*;
import static org.testng.AssertJUnit.*;
/**
* Straight swap replacement for the JETT assertEquals class, but without all the JETT baggage..
*/
public class AssertionUtils {
private static long dateTolerance = 2000;
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
Document expected = new XMLHelpers().createAsDocument(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(("<a><b><c>1</c><c>2</c><c>3</c></b><b><c>1</c><c>2</c><c>3</c></b></a>").getBytes())));
Document actual = new XMLHelpers().createAsDocument(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(("<a><b><c>2</c><c>1</c><c>3</c></b><b><c>3</c><c>2</c><c>1</c></b></a>").getBytes())));
try {
multiAssertEquals(expected,actual);
System.out.println("Failed: should have been different");
}
catch (AssertionError e) {
System.out.println("Passed: were different");
}
try {
multiAssertEquals(expected,actual,"/a/b");
System.out.println("Passed: weren't different");
}
catch (AssertionError e) {
System.out.println("Failed: shouldn't have been different");
}
}
public static void multiAssertEquals(Document expected, Document actual, String... unorderedXpaths) throws RuntimeException {
try {
XPath xpath = XPathFactory.newInstance().newXPath();
for (String x : unorderedXpaths) {
doDomSorting(expected, xpath, x);
doDomSorting(actual, xpath, x);
}
}
catch (XPathExpressionException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
jettAssertEquals(null, expected, actual);
}
private static void doDomSorting(Document doc, XPath xpath, String x) throws XPathExpressionException, IOException {
NodeList parentNodes = (NodeList) xpath.evaluate(x,doc, XPathConstants.NODESET);
for (int i=0; i<parentNodes.getLength(); i++) {
Node n = parentNodes.item(i);
List<Node> allKids = new ArrayList<>(n.getChildNodes().getLength());
for (int j=n.getChildNodes().getLength()-1; j>=0; j--) {
allKids.add(n.removeChild(n.getFirstChild()));
}
final Map<Node,String> kidsToString = new HashMap<>();
for (Node k : allKids) {
kidsToString.put(k,toString(k));
}
Collections.sort(allKids, new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
return kidsToString.get(o1).compareTo(kidsToString.get(o2));
}
});
for (Node k : allKids) {
n.appendChild(k);
}
}
}
private static String toString(Node k) throws IOException {
ToTextStream s = new ToTextStream();
StringWriter sw = new StringWriter();
s.setWriter(sw);
s.serialize(k);
return sw.toString();
}
public static void multiAssertEquals(JSONObject expected, JSONObject actual, String... unorderedXpaths) throws RuntimeException {
try {
for (String x : unorderedXpaths) {
doJsonSorting(expected, x);
doJsonSorting(actual, x);
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
jettAssertEquals(null, expected, actual);
}
private static void doJsonSorting(JSONObject doc, String x) throws XPathExpressionException, IOException, JSONException {
JXPathContext ctx = JXPathContext.newContext(doc);
String parentX = x.substring(0,x.lastIndexOf("/"));
if ("".equals(parentX)) {
parentX = "/";
}
String childName = x.substring(x.lastIndexOf("/")+1);
Iterator it = ctx.iterate(parentX);
while (it.hasNext()) {
JSONObject p = (JSONObject) it.next();
JSONArray n = p.getJSONArray(childName);
List allKids = new ArrayList<>(n.length());
for (int j=0; j<n.length(); j++) {
allKids.add(n.get(j));
}
Collections.sort(allKids, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
return o1.toString().compareTo(o2.toString());
}
});
JSONArray newArray = new JSONArray(allKids);
p.put(childName,newArray);
}
}
public static void multiAssertEquals(Object expected, Object actual) {
jettAssertEquals(null, expected, actual);
}
public static void jettAssertEquals(String message, Object expected, Object actual) {
if (actual == null) {
assertNull(message, expected);
}
else {
DataTypeEnum actualObjectType = ObjectUtil.resolveType(actual.getClass());
IAssertion asserter = AssertionProcessorFactory.getAssertionProcessor(actualObjectType);
asserter.execute(message, expected, actual, null);
}
}
public static void actionFail(String s) {
fail(s);
}
public static void actionPass(String s) {
// nothing to do
}
public static void jettAssertNull(String s, Object actualValue) {
assertNull(s, actualValue);
}
public static void jettAssertTrue(String s, boolean checkBehaviour) {
assertTrue(s, checkBehaviour);
}
public static void jettAssertFalse(String s, boolean b) {
assertFalse(s, b);
}
public static void actionException(Exception e) {
throw new AssertionError(e);
}
public static void jettAssertDatesWithTolerance(String errorMessage, Date expectedValue, Date actualValue) {
jettAssertDatesWithTolerance(errorMessage, expectedValue, actualValue, getDateTolerance());
}
public static void jettAssertDatesWithTolerance(String errorMessage, Date expectedValue, Date actualValue, long tolerance) {
if (expectedValue == null) {
assertNull(actualValue);
}
else {
assertNotNull(actualValue);
long expected = expectedValue.getTime();
long actual = expectedValue.getTime();
long diff = Math.abs(expected - actual);
if (diff > tolerance) {
if (errorMessage != null) {
fail(errorMessage);
}
else {
fail("Expected: "+expectedValue+" with a tolerance of "+tolerance+"ms, but got: "+actualValue);
}
}
}
}
public static long getDateTolerance() {
return dateTolerance;
}
public static long setDateTolerance(long dateTolerance) {
long ret = AssertionUtils.dateTolerance;
AssertionUtils.dateTolerance = dateTolerance;
return ret;
}
}