package org.exist.xquery;
import junit.framework.TestCase;
import junit.textui.TestRunner;
import org.exist.storage.DBBroker;
import org.xmldb.api.DatabaseManager;
import org.xmldb.api.base.*;
import org.xmldb.api.modules.*;
public class DeepEqualTest extends TestCase {
private final static String URI = "xmldb:exist://" + DBBroker.ROOT_COLLECTION;
private final static String DRIVER = "org.exist.xmldb.DatabaseImpl";
private XPathQueryService query;
private Collection c;
public static void main(String[] args) {
TestRunner.run(DeepEqualTest.class);
}
public DeepEqualTest(String name) {
super(name);
}
public void testAtomic1() {
assertQuery(true, "deep-equal('hello', 'hello')");
}
public void testAtomic2() {
assertQuery(false, "deep-equal('hello', 'goodbye')");
}
public void testAtomic3() {
assertQuery(true, "deep-equal(42, 42)");
}
public void testAtomic4() {
assertQuery(false, "deep-equal(42, 17)");
}
public void testAtomic5() {
assertQuery(false, "deep-equal(42, 'hello')");
}
public void testAtomic6() {
assertQuery(true, "deep-equal( 1. , xs:integer(1) )" );
assertQuery(true, "deep-equal( xs:double(1) , xs:integer(1) )" );
}
public void testEmptySeq() {
assertQuery(true, "deep-equal((), ())");
}
public void testDiffLengthSeq1() {
assertQuery(false, "deep-equal((), 42)");
}
public void testDiffLengthSeq2() {
assertQuery(false, "deep-equal((), (42, 'hello'))");
}
public void testDiffKindNodes1() {
createDocument("test", "<test key='value'>hello</test>");
assertQuery(false, "deep-equal(/test, /test/@key)");
}
public void testDiffKindNodes2() {
createDocument("test", "<test key='value'>hello</test>");
assertQuery(false, "deep-equal(/test, /test/text())");
}
public void testDiffKindNodes3() {
createDocument("test", "<test key='value'>hello</test>");
assertQuery(false, "deep-equal(/test/@key, /test/text())");
}
public void testSameNode1() {
createDocument("test", "<test key='value'>hello</test>");
assertQuery(true, "deep-equal(/test, /test)");
}
public void testSameNode2() {
createDocument("test", "<test key='value'>hello</test>");
assertQuery(true, "deep-equal(/test/@key, /test/@key)");
}
public void testSameNode3() {
createDocument("test", "<test key='value'>hello</test>");
assertQuery(true, "deep-equal(/test/text(), /test/text())");
}
public void testDocuments1() {
createDocument("test1", "<test key='value'>hello</test>");
createDocument("test2", "<test key='value'>hello</test>");
assertQuery(true, "deep-equal(xmldb:document('test1'), xmldb:document('test2'))");
}
public void testDocuments2() {
createDocument("test1", "<test key='value'>hello</test>");
createDocument("test2", "<notatest/>");
assertQuery(false, "deep-equal(xmldb:document('test1'), xmldb:document('test2'))");
}
public void testText1() {
createDocument("test", "<test><g1><a>1</a><b>2</b></g1><g2><c>1</c><d>2</d></g2></test>");
assertQuery(true, "deep-equal(//a/text(), //c/text())");
}
public void testText2() {
createDocument("test", "<test><g1><a>1</a><b>2</b></g1><g2><c>1</c><d>2</d></g2></test>");
assertQuery(false, "deep-equal(//a/text(), //b/text())");
}
public void testText3() {
createDocument("test", "<test><g1><a>1</a><b>2</b></g1><g2><c>1</c><d>2</d></g2></test>");
assertQuery(true, "deep-equal(//g1/text(), //g2/text())");
}
public void testText4() {
createDocument("test", "<test><a>12</a><b>1<!--blah-->2</b></test>");
assertQuery(false, "deep-equal(//a/text(), //b/text())");
}
public void testAttributes1() {
createDocument("test", "<test><e1 a='1'/><e2 a='1' b='2' c='1'/><e3 a='2'/></test>");
assertQuery(true, "deep-equal(//e1/@a, //e2/@a)");
}
public void testAttributes2() {
createDocument("test", "<test><e1 a='1'/><e2 a='1' b='2' c='1'/><e3 a='2'/></test>");
assertQuery(false, "deep-equal(//e1/@a, //e2/@b)");
}
public void testAttributes3() {
createDocument("test", "<test><e1 a='1'/><e2 a='1' b='2' c='1'/><e3 a='2'/></test>");
assertQuery(false, "deep-equal(//e1/@a, //e2/@c)");
}
public void testAttributes4() {
createDocument("test", "<test><e1 a='1'/><e2 a='1' b='2' c='1'/><e3 a='2'/></test>");
assertQuery(false, "deep-equal(//e1/@a, //e3/@a)");
}
public void testNSAttributes1() {
createDocument("test", "<test xmlns:n='urn:blah' xmlns:p='urn:foo' xmlns:q='urn:blah'><e1 n:a='1'/><e2 n:a='1' p:a='1' p:b='1'/><e3 n:a='2'/><e4 q:a='1'/></test>");
assertQuery(true, "declare namespace n = 'urn:blah'; declare namespace p = 'urn:foo'; declare namespace q = 'urn:blah'; deep-equal(//e1/@n:a, //e2/@n:a)");
}
public void testNSAttributes2() {
createDocument("test", "<test xmlns:n='urn:blah' xmlns:p='urn:foo' xmlns:q='urn:blah'><e1 n:a='1'/><e2 n:a='1' p:a='1' p:b='1'/><e3 n:a='2'/><e4 q:a='1'/></test>");
assertQuery(true, "declare namespace n = 'urn:blah'; declare namespace p = 'urn:foo'; declare namespace q = 'urn:blah'; deep-equal(//e1/@q:a, //e4/@n:a)");
}
public void testNSAttributes3() {
createDocument("test", "<test xmlns:n='urn:blah' xmlns:p='urn:foo' xmlns:q='urn:blah'><e1 n:a='1'/><e2 n:a='1' p:a='1' p:b='1'/><e3 n:a='2'/><e4 q:a='1'/></test>");
assertQuery(false, "declare namespace n = 'urn:blah'; declare namespace p = 'urn:foo'; declare namespace q = 'urn:blah'; deep-equal(//e1/@n:a, //e2/@p:a)");
}
public void testNSAttributes4() {
createDocument("test", "<test xmlns:n='urn:blah' xmlns:p='urn:foo' xmlns:q='urn:blah'><e1 n:a='1'/><e2 n:a='1' p:a='1' p:b='1'/><e3 n:a='2'/><e4 q:a='1'/></test>");
assertQuery(false, "declare namespace n = 'urn:blah'; declare namespace p = 'urn:foo'; declare namespace q = 'urn:blah'; deep-equal(//e1/@n:a, //e2/@p:b)");
}
public void testNSAttributes5() {
createDocument("test", "<test xmlns:n='urn:blah' xmlns:p='urn:foo' xmlns:q='urn:blah'><e1 n:a='1'/><e2 n:a='1' p:a='1' p:b='1'/><e3 n:a='2'/><e4 q:a='1'/></test>");
assertQuery(false, "declare namespace n = 'urn:blah'; declare namespace p = 'urn:foo'; declare namespace q = 'urn:blah'; deep-equal(//e1/@n:a, //e3/@n:a)");
}
public void testElements1() {
createDocument("test", "<test><a/><a/></test>");
assertQuery(true, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements2() {
createDocument("test", "<test><a/><b/></test>");
assertQuery(false, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements3() {
createDocument("test", "<test><a a='1' b='2'/><a b='2' a='1'/></test>");
assertQuery(true, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements4() {
createDocument("test", "<test><a a='1'/><a b='2' a='1'/></test>");
assertQuery(false, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements5() {
createDocument("test", "<test><a a='1' c='2'/><a b='2' a='1'/></test>");
assertQuery(false, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements6() {
createDocument("test", "<test><a a='1' b='2'/><a a='2' b='2'/></test>");
assertQuery(false, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements7() {
createDocument("test", "<test><a>hello</a><a>hello</a></test>");
assertQuery(true, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements8() {
createDocument("test", "<test><a>hello</a><a>bye</a></test>");
assertQuery(false, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements9() {
createDocument("test", "<test><a><!--blah--></a><a/></test>");
assertQuery(true, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements10() {
createDocument("test", "<test><a><b/><!--blah-->hello</a><a><b/>hello</a></test>");
assertQuery(true, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements11() {
createDocument("test", "<test><a><b/>hello</a><a>hello</a></test>");
assertQuery(false, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements12() {
createDocument("test", "<test><a><b/></a><a>hello</a></test>");
assertQuery(false, "deep-equal(/test/*[1], /test/*[2])");
}
public void testElements13() {
createDocument("test", "<test><a><b/></a><a><b/>hello</a></test>");
assertQuery(false, "deep-equal(/test/*[1], /test/*[2])");
}
//Courtesy : Dizzz
public void testElements14() {
//Includes a reference node
String query =
"let $parSpecs1 := <ParameterSpecifications/> " +
"let $funSpecs2 := " +
" <FunctionSpecifications>" +
" <FunctionName>Func2</FunctionName>" +
" { $parSpecs1 }" +
" </FunctionSpecifications>" +
"return " +
" deep-equal("+
" <FunctionVerifications>" +
" <FunctionName>Func2</FunctionName>" +
" </FunctionVerifications>" +
"," +
" <FunctionVerifications>" +
" { $funSpecs2/FunctionName }" +
" </FunctionVerifications>"+
" )";
assertQuery(true, query);
}
public void testElements15() {
String query ="let $funSpecs :="+
"<FunctionSpecifications>"+
"<FunctionName>Func2</FunctionName>"+
"</FunctionSpecifications>"+
"let $funVers1 :="+
"<FunctionVerifications>"+
"<FunctionName>Func2</FunctionName>"+
"</FunctionVerifications>"+
"let $funVers2 :="+
"<FunctionVerifications>"+
"{$funSpecs/FunctionName}"+
"</FunctionVerifications>"+
"return "+
"deep-equal($funVers1, $funVers2)";
assertQuery(true, query);
}
public void testElements16() {
// [ 1462061 ] Issue with deep-equal() "DeepestEqualBug"
String query =
"declare namespace ve = \"ournamespace\";"+
"declare function ve:functionVerifications($pars as element()*) as element() {"+
"<FunctionVerifications>"+
"<ParameterVerifications>{$pars[Name eq \"Par1\"]}</ParameterVerifications>"+
"</FunctionVerifications>"+
"};"+
"let $par1 := <Parameter><Name>Par1</Name></Parameter>"+
"let $funVers2 := "+
"<FunctionVerifications><ParameterVerifications> {$par1}"+
"</ParameterVerifications></FunctionVerifications> "+
"return "+
"deep-equal($funVers2, ve:functionVerifications($par1))";
assertQuery(true,query);
}
public void testElements17() {
// Test deep-equal is used with in-memory nodes
String query =
"let $one := <foo/> "+
"let $two := <bar/> "+
"return "+
"deep-equal($one, $two)";
assertQuery(false,query);
}
public void testReferenceNode() {
String query =
"let $expr1 := <Value>Hello</Value> "+
"return "+
"deep-equal( <Result><Value>Hello</Value></Result>,"+
"<Result><Value>{$expr1/node()}</Value></Result> )";
assertQuery(true,query);
}
public void testReferenceNode2() {
String query = "declare namespace dst = \"http://www.test.com/DeeperEqualTest\"; "
+ "declare function dst:value($value as element(Value), "
+ "$result as element(Result)) as element(Result) { "
+ "<Result><Value>{($result/Value/node(), $value/node())}</Value> </Result>}; "
+ "let $value1 := <Value>hello</Value> "
+ "let $result0 := <Result><Value/></Result> "
+ "let $result1 := dst:value($value1, $result0) "
+ "let $value2 := <Value/> "
+ "let $result2 := dst:value($value2, $result1) "
+ "return deep-equal($result1, $result2)";
assertQuery(true,query);
}
public void testReferenceNode3() {
createDocument("test", "<root><value>A</value><value>B</value></root>");
// two adjacent reference text nodes from another document should be merged into one
assertQuery(true,
"let $a := <v>{/root/value[1]/node(), /root/value[2]/node()}</v>" +
"let $b := <v>AB</v>" +
"return deep-equal($a, $b)");
// one reference node after a text node
assertQuery(true,
"let $a := <v>{/root/value[1]/node(), /root/value[2]/node()}</v>" +
"let $b := <v>A{/root/value[2]/node()}</v>" +
"return deep-equal($a, $b)");
// reference node before a text node
assertQuery(true,
"let $a := <v>{/root/value[1]/node(), /root/value[2]/node()}</v>" +
"let $b := <v>{/root/value[1]/node()}B</v>" +
"return deep-equal($a, $b)");
// reference node before an atomic value
assertQuery(true,
"let $a := <v>{/root/value[1]/node(), 'B'}</v>" +
"let $b := <v>AB</v>" +
"return deep-equal($a, $b)");
// reference node after an atomic value
assertQuery(true,
"let $a := <v>{'A', /root/value[2]/node()}</v>" +
"let $b := <v>AB</v>" +
"return deep-equal($a, $b)");
}
public void testsiblingCornerCase() {
String query = "declare namespace ve = 'http://www.test.com/deepestEqualError'; " +
"declare function ve:functionVerifications() as element(FunctionVerifications) { " +
"let $parVers := " +
"<ParameterVerifications> " +
" <Parameter/> " +
" <PassedLevel>ATP</PassedLevel> " +
" <PassedLevel>PE</PassedLevel> " +
" <PassedLevel>SPC</PassedLevel> " +
" <Specification>ATP</Specification> " +
" <Specification>PE</Specification> " +
" <Specification>SPC</Specification> " +
"</ParameterVerifications> " +
"let $dummy := $parVers/PassedLevel (: cause deep-equal bug!!! :) " +
"return " +
"<FunctionVerifications> " +
" <PassedLevel>ATP</PassedLevel> " +
" <PassedLevel>PE</PassedLevel> " +
" <PassedLevel>SPC</PassedLevel> " +
" {$parVers} " +
"</FunctionVerifications> " +
"}; " +
"let $expected := " +
" <FunctionVerifications> " +
" <PassedLevel>ATP</PassedLevel> " +
" <PassedLevel>PE</PassedLevel> " +
" <PassedLevel>SPC</PassedLevel> " +
" <ParameterVerifications> " +
" <Parameter/> " +
" <PassedLevel>ATP</PassedLevel> " +
" <PassedLevel>PE</PassedLevel> " +
" <PassedLevel>SPC</PassedLevel> " +
" <Specification>ATP</Specification> " +
" <Specification>PE</Specification> " +
" <Specification>SPC</Specification> " +
" </ParameterVerifications> " +
" </FunctionVerifications> " +
"let $got := ve:functionVerifications() " +
"return deep-equal($expected, $got)";
assertQuery(true,query);
}
public void testSequenceError1() {
String query = "declare namespace ds = \"http://www.test.com/SequenceError\"; "
+"declare function ds:result( $current as element(Result)?, "
+"$value as element(Value)?) as element(Result) {"
+"<Result> <Value>{ ($current/Value/node(), $value/node()) }</Value> </Result> };"
+"let $v1 := <Value>1234</Value> "
+"let $result1 := ds:result((), $v1) "
+"let $v2 := <Value>abcd</Value> "
+"let $expected := <Value>{($v1, $v2)/node()}</Value> "
+"let $result2 := ds:result($result1, $v2) "
+"return deep-equal($expected, $result2/Value)";
for(int i=1; i<20;i++){
System.out.println("nr="+i);
assertQuery(true,query);
}
};
public void testNSElements1() {
createDocument("test", "<test xmlns:p='urn:foo' xmlns:q='urn:foo'><p:a/><q:a/></test>");
assertQuery(true, "deep-equal(/test/*[1], /test/*[2])");
}
public void testNSElements2() {
createDocument("test", "<test xmlns:p='urn:foo' xmlns:q='urn:bar'><p:a/><q:a/></test>");
assertQuery(false, "deep-equal(/test/*[1], /test/*[2])");
}
public void testNSElements3() {
createDocument("test", "<test><a/><a xmlns:z='foo'/></test>");
assertQuery(true, "deep-equal(/test/*[1], /test/*[2])");
}
public void testForLoop() {
try {
ResourceSet rs = query.query("let $set := <root><b>test</b><c><a>test</a></c><d><a>test</a></d></root>, $test := <c><a>test</a></c> for $node in $set/* return deep-equal($node, $test)");
assertEquals(3, rs.getSize());
assertEquals("false", rs.getResource(0).getContent());
assertEquals("true", rs.getResource(1).getContent());
assertEquals("false", rs.getResource(2).getContent());
} catch (Exception e) {
fail(e.getMessage());
}
}
private void assertQuery(boolean expected, String q) {
try {
ResourceSet rs = query.query(q);
assertEquals(1, rs.getSize());
assertEquals(Boolean.toString(expected), rs.getResource(0).getContent());
} catch (Exception e) {
fail(e.getMessage());
}
}
private XMLResource createDocument(String name, String content) {
try {
XMLResource res = (XMLResource) c.createResource(name, XMLResource.RESOURCE_TYPE);
res.setContent(content);
c.storeResource(res);
return res;
} catch (Exception e) {
fail(e.getMessage());
}
return null;
}
private Collection setupTestCollection() {
try {
Collection root = DatabaseManager.getCollection(URI, "admin", "");
CollectionManagementService rootcms = (CollectionManagementService) root.getService("CollectionManagementService", "1.0");
Collection cc = root.getChildCollection("test");
if(cc != null) rootcms.removeCollection("test");
rootcms.createCollection("test");
cc = DatabaseManager.getCollection(URI+"/test", "admin", "");
assertNotNull(cc);
return cc;
} catch (Exception e) {
fail(e.getMessage());
}
return null;
}
protected void setUp() {
try {
// initialize driver
Database database = (Database) Class.forName(DRIVER).newInstance();
database.setProperty("create-database", "true");
DatabaseManager.registerDatabase(database);
c = setupTestCollection();
query = (XPathQueryService) c.getService("XPathQueryService", "1.0");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("failed setup", e);
}
}
protected void tearDown() {
try {
if (c != null) c.close();
c = null;
query = null;
} catch (XMLDBException e) {
throw new RuntimeException("failed teardown", e);
}
}
}