package org.exist.xquery; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import junit.framework.TestCase; import junit.textui.TestRunner; import org.exist.storage.DBBroker; import org.xmldb.api.DatabaseManager; import org.xmldb.api.base.Collection; import org.xmldb.api.base.Database; import org.xmldb.api.base.ResourceSet; import org.xmldb.api.base.XMLDBException; import org.xmldb.api.modules.CollectionManagementService; import org.xmldb.api.modules.XMLResource; import org.xmldb.api.modules.XPathQueryService; public class SeqOpTest 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(SeqOpTest.class); } public SeqOpTest(String name) { super(name); } public void testReverseEmpty() throws XMLDBException { assertSeq(new String[0], "reverse(())"); } public void testReverseAtomic1() throws XMLDBException { assertSeq(new String[]{"a"}, "reverse(('a'))"); } public void testReverseAtomic2() throws XMLDBException { assertSeq(new String[]{"b", "a"}, "reverse(('a', 'b'))"); } public void testReverseNodes1() throws XMLDBException { createDocument("foo", "<top><a/><b/></top>"); assertSeq(new String[]{"<a/>"}, "reverse(//a)"); } public void testReverseNodes2() throws XMLDBException { createDocument("foo", "<top><a/><b/></top>"); assertSeq(new String[]{"<b/>", "<a/>"}, "reverse(/top/*)"); } public void testReverseMixed() throws XMLDBException { createDocument("foo", "<top><a/><b/></top>"); assertSeq(new String[]{"c", "<b/>", "<a/>"}, "reverse((/top/*, 'c'))"); } public void testRemoveEmpty1() throws XMLDBException { assertSeq(new String[0], "remove((), 1)"); } public void testRemoveEmpty2() throws XMLDBException { assertSeq(new String[0], "remove((), 0)"); } public void testRemoveEmpty3() throws XMLDBException { assertSeq(new String[0], "remove((), 42)"); } public void testRemoveOutOfBounds1() throws XMLDBException { assertSeq(new String[]{"a", "b"}, "remove(('a', 'b'), 0)"); } public void testRemoveOutOfBounds2() throws XMLDBException { assertSeq(new String[]{"a", "b"}, "remove(('a', 'b'), 3)"); } public void testRemoveOutOfBounds3() throws XMLDBException { assertSeq(new String[]{"a", "b"}, "remove(('a', 'b'), -1)"); } public void testRemoveAtomic1() throws XMLDBException { assertSeq(new String[]{"b", "c"}, "remove(('a', 'b', 'c'), 1)"); } public void testRemoveAtomic2() throws XMLDBException { assertSeq(new String[]{"a", "c"}, "remove(('a', 'b', 'c'), 2)"); } public void testRemoveAtomic3() throws XMLDBException { assertSeq(new String[]{"a", "b"}, "remove(('a', 'b', 'c'), 3)"); } public void testRemoveMixed1() throws XMLDBException { createDocument("foo", "<top><a/><b/></top>"); assertSeq(new String[]{"<b/>", "a", "b", "c"}, "remove((/top/*, 'a', 'b', 'c'), 1)"); } public void testRemoveMixed2() throws XMLDBException { createDocument("foo", "<top><a/><b/></top>"); assertSeq(new String[]{"<a/>", "a", "b", "c"}, "remove((/top/*, 'a', 'b', 'c'), 2)"); } public void testRemoveMixed3() throws XMLDBException { createDocument("foo", "<top><a/><b/></top>"); assertSeq(new String[]{"<a/>", "<b/>", "b", "c"}, "remove((/top/*, 'a', 'b', 'c'), 3)"); } public void testRemoveNodes1() throws XMLDBException { createDocument("foo", "<top><a/><b/><c/></top>"); assertSeq(new String[]{"<b/>", "<c/>"}, "remove(/top/*, 1)"); } public void testRemoveNodes2() throws XMLDBException { createDocument("foo", "<top><a/><b/><c/></top>"); assertSeq(new String[]{"<a/>", "<c/>"}, "remove(/top/*, 2)"); } public void testRemoveNodes3() throws XMLDBException { createDocument("foo", "<top><a/><b/><c/></top>"); assertSeq(new String[]{"<a/>", "<b/>"}, "remove(/top/*, 3)"); } public void testInsertEmpty1() throws XMLDBException { assertSeq(new String[0], "insert-before((), 1, ())"); } public void testInsertEmpty2() throws XMLDBException { assertSeq(new String[]{"a"}, "insert-before((), 1, ('a'))"); } public void testInsertEmpty3() throws XMLDBException { assertSeq(new String[]{"a"}, "insert-before(('a'), 1, ())"); } public void testInsertOutOfBounds1() throws XMLDBException { assertSeq(new String[]{"c", "d", "a", "b"}, "insert-before(('a', 'b'), 0, ('c', 'd'))"); } public void testInsertOutOfBounds2() throws XMLDBException { assertSeq(new String[]{"a", "b", "c", "d"}, "insert-before(('a', 'b'), 3, ('c', 'd'))"); } public void testInsertOutOfBounds3() throws XMLDBException { assertSeq(new String[]{"a", "b", "c", "d"}, "insert-before(('a', 'b'), 4, ('c', 'd'))"); } public void testInsertAtomic1() throws XMLDBException { assertSeq(new String[]{"a", "c", "d", "b"}, "insert-before(('a', 'b'), 2, ('c', 'd'))"); } public void testInsertAtomic2() throws XMLDBException { assertSeq(new String[]{"c", "d", "a", "b"}, "insert-before(('a', 'b'), 1, ('c', 'd'))"); } public void testInsertAtomic3() throws XMLDBException { assertSeq(new String[]{"a", "a", "b", "b"}, "insert-before(('a', 'b'), 2, ('a', 'b'))"); } public void testInsertNodes1() throws XMLDBException { createDocument("foo", "<top><x><a/><b/></x><y><c/><d/></y></top>"); assertSeq(new String[]{"<a/>", "<c/>", "<d/>", "<b/>"}, "insert-before(/top/x/*, 2, /top/y/*)"); } public void testInsertNodes2() throws XMLDBException { createDocument("foo", "<top><x><a/><b/></x><y><c/><d/></y></top>"); assertSeq(new String[]{"<c/>", "<d/>", "<a/>", "<b/>"}, "insert-before(/top/x/*, 1, /top/y/*)"); } public void testInsertNodes3() throws XMLDBException { createDocument("foo", "<top><x><a/><b/></x><y><c/><d/></y></top>"); assertSeq(new String[]{"<a/>", "<b/>", "<c/>", "<d/>"}, "insert-before(/top/x/*, 3, /top/y/*)"); } // TODO: currently fails because duplicate nodes are removed public void testInsertNodes4() throws XMLDBException { createDocument("foo", "<top><x><a/><b/></x><y><c/><d/></y></top>"); assertSeq(new String[]{"<a/>", "<a/>", "<b/>", "<b/>"}, "insert-before(/top/x/*, 2, /top/x/*)"); } public void testInsertMixed1() throws XMLDBException { createDocument("foo", "<top><x><a/><b/></x><y><c/><d/></y></top>"); assertSeq(new String[]{"<a/>", "c", "<b/>"}, "insert-before(/top/x/*, 2, ('c'))"); } // TODO: currently fails because duplicate nodes are removed public void testInsertMixed2() throws XMLDBException { createDocument("foo", "<top><x><a/><b/></x><y><c/><d/></y></top>"); assertSeq(new String[]{"<a/>", "<a/>", "<b/>", "<b/>", "c"}, "insert-before((/top/x/*, 'c'), 2, /top/x/*)"); } private void assertSeq(String[] expected, String q) throws XMLDBException { ResourceSet rs = query.query(q); assertEquals(expected.length, rs.getSize()); List a = Arrays.asList(expected); List r = new ArrayList((int) rs.getSize()); for (int i = 0; i < rs.getSize(); i++) r.add(rs.getResource(i).getContent()); if (!a.equals(r)) fail("expected " + a + ", got " + r); } private XMLResource createDocument(String name, String content) throws XMLDBException { XMLResource res = (XMLResource) c.createResource(name, XMLResource.RESOURCE_TYPE); res.setContent(content); c.storeResource(res); return res; } private Collection setupTestCollection() throws XMLDBException { Collection root = DatabaseManager.getCollection(URI, "admin", ""); CollectionManagementService rootcms = (CollectionManagementService) root.getService("CollectionManagementService", "1.0"); Collection c = root.getChildCollection("test"); if(c != null) rootcms.removeCollection("test"); rootcms.createCollection("test"); c = DatabaseManager.getCollection(URI+"/test", "admin", ""); assertNotNull(c); return c; } 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); } } }