/*
* eXist Open Source Native XML Database
* Copyright (C) 2016 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.exist.xquery;
import org.exist.storage.DBBroker;
import org.exist.security.Subject;
import org.exist.xquery.value.BinaryValue;
import org.junit.Test;
import org.easymock.EasyMock;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
/**
* @author Adam Retter <adam.retter@googlemail.com>
*/
public class XQueryContextTest {
@Test
public void prepareForExecution_setsUserFromSession() {
//partial mock context
XQueryContext context = EasyMock.createMockBuilder(XQueryContext.class)
.withConstructor()
.withArgs()
.addMockedMethod("getUserFromHttpSession")
.addMockedMethod("getBroker")
.createMock();
DBBroker mockBroker = createMock(DBBroker.class);
Subject mockSubject = createMock(Subject.class);
//expectations
expect(context.getUserFromHttpSession()).andReturn(mockSubject);
expect(context.getBroker()).andReturn(mockBroker).times(2);
mockBroker.pushSubject(mockSubject);
//test
replay(context);
context.prepareForExecution();
verify(context);
}
/**
* Test to ensure that BinaryValueInstances are
* correctly cleaned up by the XQueryContext
* between reuse of the context
*/
@Test
public void cleanUp_BinaryValueInstances() throws NoSuchFieldException, IllegalAccessException, IOException {
final XQueryContext context = new XQueryContext();
final XQueryWatchDog mockWatchdog = createMock(XQueryWatchDog.class);
context.setWatchDog(mockWatchdog);
final BinaryValue mockBin1 = createMock(BinaryValue.class);
final BinaryValue mockBin2 = createMock(BinaryValue.class);
final BinaryValue mockBin3 = createMock(BinaryValue.class);
final BinaryValue mockBin4 = createMock(BinaryValue.class);
final BinaryValue mockBin5 = createMock(BinaryValue.class);
final BinaryValue mockBin6 = createMock(BinaryValue.class);
final BinaryValue mockBin7 = createMock(BinaryValue.class);
// expectations on our mocks
mockBin1.close();
expectLastCall().times(1);
mockBin2.close();
expectLastCall().times(1);
mockBin3.close();
expectLastCall().times(1);
mockBin4.close();
expectLastCall().times(1);
mockBin5.close();
expectLastCall().times(1);
mockBin6.close();
expectLastCall().times(1);
mockBin7.close();
expectLastCall().times(1);
mockWatchdog.reset();
expectLastCall().times(3);
// prepare our mocks for our test
replay(mockBin1, mockBin2, mockBin3, mockBin4, mockBin5, mockBin6, mockBin7, mockWatchdog);
/* round 1 */
// use some binary streams
context.registerBinaryValueInstance(mockBin1);
context.registerBinaryValueInstance(mockBin2);
context.registerBinaryValueInstance(mockBin3);
assertEquals(3, countBinaryValueInstances(context));
assertEquals(1, countCleanupTasks(context));
// cleanup those streams
context.runCleanupTasks();
assertEquals(0, countBinaryValueInstances(context));
//reset the context (for reuse(), just as XQueryPool#returnCompiledXQuery(org.exist.source.Source, CompiledXQuery) would do)
context.reset();
assertEquals(0, countCleanupTasks(context));
/* round 2, let's reuse the context... */
// use some more binary streams
context.registerBinaryValueInstance(mockBin4);
context.registerBinaryValueInstance(mockBin5);
assertEquals(2, countBinaryValueInstances(context));
assertEquals(1, countCleanupTasks(context));
// cleanup those streams
context.runCleanupTasks();
assertEquals(0, countBinaryValueInstances(context));
//reset the context (for reuse(), just as XQueryPool#returnCompiledXQuery(org.exist.source.Source, CompiledXQuery) would do)
context.reset();
assertEquals(0, countCleanupTasks(context));
/* round 3, let's reuse the context a second time... */
// again, use some more binary streams
context.registerBinaryValueInstance(mockBin6);
context.registerBinaryValueInstance(mockBin7);
assertEquals(2, countBinaryValueInstances(context));
assertEquals(1, countCleanupTasks(context));
// cleanup those streams
context.runCleanupTasks();
assertEquals(0, countBinaryValueInstances(context));
//reset the context (for reuse(), just as XQueryPool#returnCompiledXQuery(org.exist.source.Source, CompiledXQuery) would do)
context.reset();
assertEquals(0, countCleanupTasks(context));
// verify the expectations of our mocks
verify(mockBin1, mockBin2, mockBin3, mockBin4, mockBin5, mockBin6, mockBin7, mockWatchdog);
}
private int countBinaryValueInstances(final XQueryContext context) throws NoSuchFieldException, IllegalAccessException {
final Field fldBinaryValueInstances = context.getClass().getDeclaredField("binaryValueInstances");
fldBinaryValueInstances.setAccessible(true);
final List<BinaryValue> binaryValueInstances = (List<BinaryValue>)fldBinaryValueInstances.get(context);
return binaryValueInstances.size();
}
private int countCleanupTasks(final XQueryContext context) throws NoSuchFieldException, IllegalAccessException {
final Field fldCleanupTasks = context.getClass().getDeclaredField("cleanupTasks");
fldCleanupTasks.setAccessible(true);
final List<XQueryContext.CleanupTask> cleanupTasks = (List<XQueryContext.CleanupTask>)fldCleanupTasks.get(context);
return cleanupTasks.size();
}
}