Skip to content

Commit 21803b9

Browse files
committed
[test] Further tests to ensure that context map attributes are cleared
1 parent b1f94f2 commit 21803b9

File tree

5 files changed

+362
-77
lines changed

5 files changed

+362
-77
lines changed

exist-core/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,7 @@
680680
<exclude>src/test/java/org/exist/util/CollectionOfArrayIteratorTest.java</exclude>
681681
<exclude>src/main/java/org/exist/xquery/Cardinality.java</exclude>
682682
<exclude>src/test/java/org/exist/xquery/ImportModuleTest.java</exclude>
683+
<exclude>src/test/java/org/exist/xquery/XQueryContextAttributesTest.java</exclude>
683684
<exclude>src/main/java/org/exist/xquery/functions/map/MapType.java</exclude>
684685
<exclude>src/test/java/org/exist/xquery/functions/session/AbstractSessionTest.java</exclude>
685686
<exclude>src/test/java/org/exist/xquery/functions/xmldb/AbstractXMLDBTest.java</exclude>
@@ -819,6 +820,7 @@ The original license statement is also included below.]]></preamble>
819820
<include>src/test/java/org/exist/util/CollectionOfArrayIteratorTest.java</include>
820821
<include>src/main/java/org/exist/xquery/Cardinality.java</include>
821822
<include>src/test/java/org/exist/xquery/ImportModuleTest.java</include>
823+
<include>src/test/java/org/exist/xquery/XQueryContextAttributesTest.java</include>
822824
<include>src/main/java/org/exist/xquery/functions/map/MapType.java</include>
823825
<include>src/test/java/org/exist/xquery/functions/session/AbstractSessionTest.java</include>
824826
<include>src/test/java/org/exist/xquery/functions/xmldb/AbstractXMLDBTest.java</include>
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/*
2+
* Copyright (C) 2014, Evolved Binary Ltd
3+
*
4+
* This file was originally ported from FusionDB to eXist-db by
5+
* Evolved Binary, for the benefit of the eXist-db Open Source community.
6+
* Only the ported code as it appears in this file, at the time that
7+
* it was contributed to eXist-db, was re-licensed under The GNU
8+
* Lesser General Public License v2.1 only for use in eXist-db.
9+
*
10+
* This license grant applies only to a snapshot of the code as it
11+
* appeared when ported, it does not offer or infer any rights to either
12+
* updates of this source code or access to the original source code.
13+
*
14+
* The GNU Lesser General Public License v2.1 only license follows.
15+
*
16+
* ---------------------------------------------------------------------
17+
*
18+
* Copyright (C) 2014, Evolved Binary Ltd
19+
*
20+
* This library is free software; you can redistribute it and/or
21+
* modify it under the terms of the GNU Lesser General Public
22+
* License as published by the Free Software Foundation; version 2.1.
23+
*
24+
* This library is distributed in the hope that it will be useful,
25+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
26+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27+
* Lesser General Public License for more details.
28+
*
29+
* You should have received a copy of the GNU Lesser General Public
30+
* License along with this library; if not, write to the Free Software
31+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32+
*/
33+
package org.exist.xquery;
34+
35+
import com.evolvedbinary.j8fu.function.Function2E;
36+
import com.evolvedbinary.j8fu.tuple.Tuple2;
37+
import org.exist.EXistException;
38+
import org.exist.collections.Collection;
39+
import org.exist.collections.triggers.TriggerException;
40+
import org.exist.dom.persistent.BinaryDocument;
41+
import org.exist.security.PermissionDeniedException;
42+
import org.exist.source.DBSource;
43+
import org.exist.source.Source;
44+
import org.exist.source.StringSource;
45+
import org.exist.storage.BrokerPool;
46+
import org.exist.storage.DBBroker;
47+
import org.exist.storage.XQueryPool;
48+
import org.exist.storage.lock.Lock;
49+
import org.exist.storage.txn.Txn;
50+
import org.exist.test.ExistEmbeddedServer;
51+
import org.exist.util.LockException;
52+
import org.exist.xmldb.XmldbURI;
53+
import org.exist.xquery.value.Sequence;
54+
import org.junit.ClassRule;
55+
import org.junit.Test;
56+
57+
import java.io.IOException;
58+
import java.io.InputStream;
59+
import java.util.Optional;
60+
import java.util.Properties;
61+
62+
import static com.evolvedbinary.j8fu.tuple.Tuple.Tuple;
63+
import static org.junit.Assert.*;
64+
65+
/**
66+
* @author <a href="mailto:[email protected]">Adam Retter</a>
67+
*/
68+
public class XQueryContextAttributesTest {
69+
70+
@ClassRule
71+
public static final ExistEmbeddedServer existEmbeddedServer = new ExistEmbeddedServer(true, true);
72+
73+
@Test
74+
public void attributesOfMainModuleContextCleared() throws EXistException, LockException, TriggerException, PermissionDeniedException, IOException, XPathException {
75+
final BrokerPool brokerPool = existEmbeddedServer.getBrokerPool();
76+
try (final DBBroker broker = brokerPool.get(Optional.of(brokerPool.getSecurityManager().getSystemSubject()));
77+
final Txn transaction = brokerPool.getTransactionManager().beginTransaction()) {
78+
79+
final XmldbURI mainQueryUri = XmldbURI.create("/db/query1.xq");
80+
final Source mainQuery = new StringSource("<not-important/>");
81+
final DBSource mainQuerySource = storeQuery(broker, transaction, mainQueryUri, mainQuery);
82+
83+
final XQueryContext escapedMainQueryContext = withCompiledQuery(broker, mainQuerySource, mainCompiledQuery -> {
84+
final XQueryContext mainQueryContext = mainCompiledQuery.getContext();
85+
86+
mainQueryContext.setAttribute("attr1", "value1");
87+
mainQueryContext.setAttribute("attr2", "value2");
88+
89+
// execute the query
90+
final Sequence result = executeQuery(broker, mainCompiledQuery);
91+
assertEquals(1, result.getItemCount());
92+
93+
// intentionally escape the context from the lambda
94+
return mainQueryContext;
95+
});
96+
97+
assertNull(escapedMainQueryContext.getAttribute("attr1"));
98+
assertNull(escapedMainQueryContext.getAttribute("attr2"));
99+
assertTrue(escapedMainQueryContext.attributes.isEmpty());
100+
101+
transaction.commit();
102+
}
103+
}
104+
105+
@Test
106+
public void attributesOfLibraryModuleContextCleared() throws EXistException, LockException, TriggerException, PermissionDeniedException, IOException, XPathException {
107+
final BrokerPool brokerPool = existEmbeddedServer.getBrokerPool();
108+
try (final DBBroker broker = brokerPool.get(Optional.of(brokerPool.getSecurityManager().getSystemSubject()));
109+
final Txn transaction = brokerPool.getTransactionManager().beginTransaction()) {
110+
111+
final XmldbURI libraryQueryUri = XmldbURI.create("/db/mod1.xqm");
112+
final Source libraryQuery = new StringSource(
113+
"module namespace mod1 = 'http://mod1';\n" +
114+
"declare function mod1:f1() { <not-important/> };"
115+
);
116+
storeQuery(broker, transaction, libraryQueryUri, libraryQuery);
117+
118+
final XmldbURI mainQueryUri = XmldbURI.create("/db/query1.xq");
119+
final Source mainQuery = new StringSource(
120+
"import module namespace mod1 = 'http://mod1' at 'xmldb:exist://" + libraryQueryUri + "';\n" +
121+
"mod1:f1()"
122+
);
123+
final DBSource mainQuerySource = storeQuery(broker, transaction, mainQueryUri, mainQuery);
124+
125+
final Tuple2<XQueryContext, ModuleContext> escapedContexts = withCompiledQuery(broker, mainQuerySource, mainCompiledQuery -> {
126+
final XQueryContext mainQueryContext = mainCompiledQuery.getContext();
127+
128+
// get the context of the library module
129+
final Module[] libraryModules = mainQueryContext.getModules("http://mod1");
130+
assertEquals(1, libraryModules.length);
131+
assertTrue(libraryModules[0] instanceof ExternalModule);
132+
final ExternalModule libraryModule = (ExternalModule) libraryModules[0];
133+
final XQueryContext libraryQueryContext = libraryModule.getContext();
134+
assertTrue(libraryQueryContext instanceof ModuleContext);
135+
136+
libraryQueryContext.setAttribute("attr1", "value1");
137+
libraryQueryContext.setAttribute("attr2", "value2");
138+
139+
// execute the query
140+
final Sequence result = executeQuery(broker, mainCompiledQuery);
141+
assertEquals(1, result.getItemCount());
142+
143+
// intentionally escape the contexts from the lambda
144+
return Tuple(mainQueryContext, (ModuleContext) libraryQueryContext);
145+
});
146+
147+
final XQueryContext escapedMainQueryContext = escapedContexts._1;
148+
final ModuleContext escapedLibraryQueryContext = escapedContexts._2;
149+
assertTrue(escapedMainQueryContext != escapedLibraryQueryContext);
150+
151+
assertNull(escapedMainQueryContext.getAttribute("attr1"));
152+
assertNull(escapedMainQueryContext.getAttribute("attr2"));
153+
assertTrue(escapedMainQueryContext.attributes.isEmpty());
154+
155+
assertNull(escapedLibraryQueryContext.getAttribute("attr1"));
156+
assertNull(escapedLibraryQueryContext.getAttribute("attr2"));
157+
assertTrue(escapedLibraryQueryContext.attributes.isEmpty());
158+
159+
transaction.commit();
160+
}
161+
}
162+
163+
private static DBSource storeQuery(final DBBroker broker, final Txn transaction, final XmldbURI uri, final Source source) throws IOException, PermissionDeniedException, TriggerException, LockException, EXistException {
164+
try (final InputStream is = source.getInputStream()) {
165+
try (final Collection collection = broker.openCollection(uri.removeLastSegment(), Lock.LockMode.WRITE_LOCK)) {
166+
final BinaryDocument doc = collection.addBinaryResource(transaction, broker, uri.lastSegment(), is, "application/xquery", -1);
167+
168+
return new DBSource(broker, doc, false);
169+
}
170+
}
171+
}
172+
173+
private static <T> T withCompiledQuery(final DBBroker broker, final Source source, final Function2E<CompiledXQuery, T, XPathException, PermissionDeniedException> op) throws XPathException, PermissionDeniedException, IOException {
174+
final BrokerPool pool = broker.getBrokerPool();
175+
final XQuery xqueryService = pool.getXQueryService();
176+
final XQueryPool xqueryPool = pool.getXQueryPool();
177+
final CompiledXQuery compiledQuery = compileQuery(broker, xqueryService, xqueryPool, source);
178+
try {
179+
return op.apply(compiledQuery);
180+
} finally {
181+
if (compiledQuery != null) {
182+
xqueryPool.returnCompiledXQuery(source, compiledQuery);
183+
}
184+
}
185+
}
186+
187+
private static CompiledXQuery compileQuery(final DBBroker broker, final XQuery xqueryService, final XQueryPool xqueryPool, final Source query) throws PermissionDeniedException, XPathException, IOException {
188+
CompiledXQuery compiled = xqueryPool.borrowCompiledXQuery(broker, query);
189+
XQueryContext context;
190+
if (compiled == null) {
191+
context = new XQueryContext(broker.getBrokerPool());
192+
} else {
193+
context = compiled.getContext();
194+
context.prepareForReuse();
195+
}
196+
197+
if (compiled == null) {
198+
compiled = xqueryService.compile(broker, context, query);
199+
} else {
200+
compiled.getContext().updateContext(context);
201+
context.getWatchDog().reset();
202+
}
203+
204+
return compiled;
205+
}
206+
207+
static Sequence executeQuery(final DBBroker broker, final CompiledXQuery compiledXQuery) throws PermissionDeniedException, XPathException {
208+
final BrokerPool pool = broker.getBrokerPool();
209+
final XQuery xqueryService = pool.getXQueryService();
210+
return xqueryService.execute(broker, compiledXQuery, null, new Properties());
211+
}
212+
}

0 commit comments

Comments
 (0)