/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
licenses@blazegraph.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.bigdata.rdf.sail.webapp;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import junit.framework.Test;
import org.openrdf.model.Graph;
import org.openrdf.model.Literal;
import org.openrdf.model.URI;
import org.openrdf.model.impl.GraphImpl;
import org.openrdf.model.impl.LiteralImpl;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.RDFS;
import org.openrdf.rio.RDFFormat;
import com.bigdata.journal.IIndexManager;
import com.bigdata.rdf.sail.webapp.client.RemoteRepository.AddOp;
import com.bigdata.rdf.store.BD;
/**
* Proxied test suite.
*
* @param <S>
*
* TODO Should test GET as well as POST (this requires that we configured the
* client differently).
*/
public class Test_REST_DESCRIBE<S extends IIndexManager> extends
AbstractTestNanoSparqlClient<S> {
public Test_REST_DESCRIBE() {
}
public Test_REST_DESCRIBE(final String name) {
super(name);
}
public static Test suite() {
return ProxySuiteHelper.suiteWhenStandalone(Test_REST_DESCRIBE.class,
"test.*", TestMode.quads
// , TestMode.sids
// , TestMode.triples
);
}
public void test_GET_DESCRIBE_RDFXML() throws Exception {
doDescribeTest("GET", RDFFormat.RDFXML);
}
public void test_GET_DESCRIBE_NTRIPLES() throws Exception {
doDescribeTest("GET", RDFFormat.NTRIPLES);
}
public void test_GET_DESCRIBE_N3() throws Exception {
doDescribeTest("GET", RDFFormat.N3);
}
public void test_GET_DESCRIBE_TURTLE() throws Exception {
doDescribeTest("GET", RDFFormat.TURTLE);
}
public void test_GET_DESCRIBE_TRIG() throws Exception {
doDescribeTest("GET", RDFFormat.TRIG);
}
public void test_GET_DESCRIBE_TRIX() throws Exception {
doDescribeTest("GET", RDFFormat.TRIX);
}
public void test_POST_DESCRIBE_RDFXML() throws Exception {
doDescribeTest("POST", RDFFormat.RDFXML);
}
public void test_POST_DESCRIBE_NTRIPLES() throws Exception {
doDescribeTest("POST", RDFFormat.NTRIPLES);
}
public void test_POST_DESCRIBE_N3() throws Exception {
doDescribeTest("POST", RDFFormat.N3);
}
public void test_POST_DESCRIBE_TURTLE() throws Exception {
doDescribeTest("POST", RDFFormat.TURTLE);
}
public void test_POST_DESCRIBE_TRIG() throws Exception {
doDescribeTest("POST", RDFFormat.TRIG);
}
public void test_POST_DESCRIBE_TRIX() throws Exception {
doDescribeTest("POST", RDFFormat.TRIX);
}
/**
* I am not quite sure about the origin of this test. It appears to have been
* related to the conversion from apache http to jetty for the client API. I
* think that it was probably developed by Martyn. bbt.
*
* @see <a href="http://trac.bigdata.com/ticket/967"> Replace Apache Http
* Components with jetty http client (was Roll forward the apache http
* components dependency to 4.3.3) </a>
*
* @throws Exception
*/
public void test976_describeStress() throws Exception {
doStressDescribeTest("GET", RDFFormat.RDFXML, 100 /** tasks **/, 50 /** threads **/, 500 /** statements **/);
}
protected void doStressDescribeTest(final String method,
final RDFFormat format, final int tasks, final int threads,
final int statements) throws Exception {
final URI person = new URIImpl(BD.NAMESPACE + "Person");
final URI likes = new URIImpl(BD.NAMESPACE + "likes");
final URI rdf = new URIImpl(BD.NAMESPACE + "RDF");
final URI rdfs = new URIImpl(BD.NAMESPACE + "RDFS");
{
// create a large number of mikes and bryans
final Graph g = new GraphImpl();
for (int n = 0; n < statements; n++) {
final URI miken = new URIImpl(BD.NAMESPACE + "Mike#" + n);
final URI bryann = new URIImpl(BD.NAMESPACE + "Bryan#" + n);
final Literal nameMiken = new LiteralImpl("Mike#" + n);
final Literal nameBryann = new LiteralImpl("Bryan#" + n);
g.add(miken, RDF.TYPE, person);
g.add(miken, likes, rdf);
g.add(miken, RDFS.LABEL, nameMiken);
g.add(bryann, RDF.TYPE, person);
g.add(bryann, likes, rdfs);
g.add(bryann, RDFS.LABEL, nameBryann);
}
m_repo.add(new AddOp(g));
}
// Run the DESCRIBE query and verify the results (non-empty).
{
final String queryStr = "prefix bd: <" + BD.NAMESPACE + "> " + //
"prefix rdf: <" + RDF.NAMESPACE + "> " + //
"prefix rdfs: <" + RDFS.NAMESPACE + "> " + //
"DESCRIBE ?x " + //
"WHERE { " + //
" ?x rdf:type bd:Person . " + //
" ?x bd:likes bd:RDF " + //
"}";
final AtomicInteger errorCount = new AtomicInteger();
final Callable<Void> task = new Callable<Void>() {
@Override
public Void call() throws Exception {
try {
final Graph actual = asGraph(m_repo
.prepareGraphQuery(queryStr));
assertTrue(!actual.isEmpty());
return null;
} catch (Exception e) {
log.warn("Call failure", e);
errorCount.incrementAndGet();
throw e;
}
}
};
final int threadCount = Thread.activeCount();
final ExecutorService exec = Executors.newFixedThreadPool(threads);
for (int r = 0; r < tasks; r++) {
exec.submit(task);
}
exec.shutdown();
exec.awaitTermination(2000, TimeUnit.SECONDS);
// force shutdown
exec.shutdownNow();
int loops = 20;
while (Thread.activeCount() > threadCount && --loops > 0) {
Thread.sleep(500);
if (log.isTraceEnabled())
log.trace("Extra threads: "
+ (Thread.activeCount() - threadCount));
}
if (log.isInfoEnabled())
log.info("Return with extra threads: "
+ (Thread.activeCount() - threadCount));
assertTrue(errorCount.get() == 0);
}
}
}