package edu.kit.aifb.cumulus.webapp;
import static edu.kit.aifb.cumulus.WebTestUtils.clean;
import static edu.kit.aifb.cumulus.WebTestUtils.newTripleStore;
import static edu.kit.aifb.cumulus.WebTestUtils.numOfRes;
import static edu.kit.aifb.cumulus.util.Util.parseNX;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import java.util.Vector;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.httpclient.methods.GetMethod;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openrdf.http.client.BackgroundTupleResult;
import org.openrdf.http.protocol.Protocol;
import org.openrdf.model.Statement;
import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.impl.ValueFactoryImpl;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.resultio.QueryResultIO;
import org.openrdf.query.resultio.TupleQueryResultFormat;
import org.openrdf.query.resultio.TupleQueryResultParser;
import org.openrdf.query.resultio.TupleQueryResultParserRegistry;
import org.openrdf.repository.sail.SailRepository;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFParser;
import org.openrdf.rio.Rio;
import org.openrdf.rio.helpers.StatementCollector;
import edu.kit.aifb.cumulus.AbstractCumulusWebTest;
import edu.kit.aifb.cumulus.StubServletOutputStream;
import edu.kit.aifb.cumulus.WebTestUtils;
import edu.kit.aifb.cumulus.framework.Environment;
import edu.kit.aifb.cumulus.store.RepositoryManager;
import edu.kit.aifb.cumulus.store.sesame.CumulusRDFSail;
import edu.kit.aifb.cumulus.webapp.endpoint.SesameHTTPProtocolEndpoint;
/**
* Test the SesameHTTPRepositoryAdapter for the use of HttpRepository.
*
* @author Yongtao
*
*/
public class SesameHTTPRepositoryTest extends AbstractCumulusWebTest {
protected SesameHTTPProtocolEndpoint _classUnderTest;
private static ValueFactory valueFactory = ValueFactoryImpl.getInstance();
private static final String DEVICE = "<http://gridpedia.org/id/Device>";
public static final String DATA_NT = "src/test/resources/triples_gridpedia.nt",
DATA_NT_LOCAL = "src/test/resources/triples_gridpedia_localhost.nt",
DATA_RDF_XML = "src/test/resources/triples_gridpedia.rdf",
DATA_NQ = "src/test/resources/quads.nq";
/** BASE_URI **/
private static final String BASE_URI = "/cumulusrdf-web-module/";
/** HTTP method "GET".*/
private static final String METHOD_GET = "GET";
/** HTTP method "POST". */
private static final String METHOD_POST = "POST";
/** HTTP method "PUT". */
private static final String METHOD_PUT = "PUT";
private static final String MIMETYPE_TXT_N3 = "text/n3";
private static final String MIMETYPE_RDF_XML = "application/rdf+xml";
private static final String MIMETYPE_WWW_FORM = "application/x-www-form-urlencoded";
private static final String UTF_8 = "UTF-8";
protected ServletContext _context;
private static final String REPO_ID = "repo";
//CHECKSTYLE:OFF
private String[] _data = {
"<http://gridpedia.org/id/Device> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . \n <http://gridpedia.org/id/Device> <http://semantic-mediawiki.org/swivt/1.0#page> <http://gridpedia.org/wiki/Device> .",
"<http://gridpedia.org/id/Device> <http://www.w3.org/2000/01/rdf-schema#label> \"Device\" .",
"<http://gridpedia.org/id/Device> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://gridpedia.org/id/Actor> . \n <http://gridpedia.org/id/Device> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://gridpedia.org/id/Actor> ."
};
//CHECKSTYLE:ON
/**
* Setup fixture for all tests.
*
* @throws Exception never otherwise tests fail.
*/
@BeforeClass
public static void setUp() throws Exception {
TRIPLE_STORE = newTripleStore();
SAIL = new CumulusRDFSail(TRIPLE_STORE);
REPOSITORY = new SailRepository(SAIL);
REPOSITORY.initialize();
RepositoryManager.getInstance().addRepository(REPO_ID, REPOSITORY, true);
}
/**
* Teardown fixture for each test.
* Basically deletes all data in the store.
*
* @throws Exception hopefully never, otherwise the corresponding test fails.
*/
@After
public void afterEachTest() throws Exception {
clean(TRIPLE_STORE);
}
/**
* Setup fixture for each test.
* Initializes mock stuff and load sample data.
*
* @throws Exception hopefully never, otherwise the corresponding test fails.
*/
@Before
public void beforeEachTest() throws Exception {
_context = mock(ServletContext.class);
_classUnderTest = spy(new SesameHTTPProtocolEndpoint());
doReturn(_context).when(_classUnderTest).getServletContext();
when(_context.getNamedDispatcher(anyString())).thenReturn(mock(RequestDispatcher.class));
}
/**
* mock the HttpServletRequest.
*
* @param uri the uri
* @param method the method e.g. "GET" and "POST"
* @return the mocked HttpServletRequest object
*/
private static HttpServletRequest mockHttpRequest(final String uri, final String method) {
final HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getRequestURI()).thenReturn(uri);
when(request.getMethod()).thenReturn(method);
when(request.getRequestDispatcher(anyString())).thenReturn(mock(RequestDispatcher.class));
return request;
}
/**
* test getting the protocol Version.
* @throws Exception the test would fails if exception occurs
*/
@Test
public void testVersion() throws Exception {
File tmp = WebTestUtils.tmpFile();
final ServletOutputStream servletOutputStream = new StubServletOutputStream(tmp);
final HttpServletRequest request = mockHttpRequest(BASE_URI + Protocol.PROTOCOL, METHOD_GET);
final HttpServletResponse response = mock(HttpServletResponse.class);
when(response.getOutputStream()).thenReturn(servletOutputStream);
_classUnderTest.service(request, response);
BufferedReader br = new BufferedReader(new FileReader(tmp));
String version = br.readLine();
br.close();
assertTrue(version.equals(Protocol.VERSION));
servletOutputStream.close();
}
/**
* test statements related operations.
* @throws Exception Exception the test would fails if exception occurs
*/
@Test
public void testStatements() throws Exception {
//test add Statements
for (final String tripleAsString : _data) {
final Statement triple = parseNX(tripleAsString).iterator().next();
final Value[] query = new Value[] { triple.getSubject(), triple.getPredicate(), triple.getObject() };
TRIPLE_STORE.removeData(query);
//ensure the repository contains not statements to be added
int howManyTriplesForPattern = numOfRes(TRIPLE_STORE.query(query));
assertEquals("This triple " + tripleAsString + " mustn't exist on store", 0, howManyTriplesForPattern);
String uri = BASE_URI + Protocol.REPOSITORIES + "/" + REPO_ID + "/" + Protocol.STATEMENTS;
final ServletInputStream stream = new ServletInputStream() {
final InputStream _inputStream = new ByteArrayInputStream(tripleAsString.getBytes(Environment.CHARSET_UTF8));
@Override
public int read() throws IOException {
return _inputStream.read();
}
};
final HttpServletRequest request = mockHttpRequest(uri, METHOD_PUT);
when(request.getInputStream()).thenReturn(stream);
when(request.getContentType()).thenReturn(MIMETYPE_TXT_N3);
when(request.getCharacterEncoding()).thenReturn(UTF_8);
File tmp = WebTestUtils.tmpFile();
final ServletOutputStream servletOutputStream = new StubServletOutputStream(tmp);
final HttpServletResponse response = mock(HttpServletResponse.class);
when(response.getOutputStream()).thenReturn(servletOutputStream);
_classUnderTest.service(request, response);
verify(response).setStatus(HttpServletResponse.SC_NO_CONTENT);
int howManyTriplesOnTheStore = numOfRes(TRIPLE_STORE.query(query));
assertEquals(1, howManyTriplesOnTheStore);
}
}
/**
* test get Statemetns.
* @throws Exception The test would fails if Exception occurs
*/
@Test
public void testGetStatements() throws Exception {
//insert some statments first
for (final String tripleAsString : _data) {
final Statement triple = parseNX(tripleAsString).iterator().next();
TRIPLE_STORE.addData(triple);
}
//test get the statements
String uri = BASE_URI + Protocol.REPOSITORIES + "/" + REPO_ID + "/" + Protocol.STATEMENTS;
File tmp = WebTestUtils.tmpFile();
final ServletOutputStream servletOutputStream = new StubServletOutputStream(tmp);
final HttpServletRequest request = mockHttpRequest(uri, METHOD_GET);
when(request.getParameter(Protocol.SUBJECT_PARAM_NAME)).thenReturn(DEVICE);
when(request.getParameter(Protocol.ACCEPT_PARAM_NAME)).thenReturn(MIMETYPE_RDF_XML);
when(request.getCharacterEncoding()).thenReturn(UTF_8);
final HttpServletResponse response = mock(HttpServletResponse.class);
when(response.getOutputStream()).thenReturn(servletOutputStream);
GetMethod method = new GetMethod(uri);
RDFFormat format = RDFFormat.RDFXML;
RDFParser parser = Rio.createParser(format, valueFactory);
parser.setParserConfig(parser.getParserConfig());
StatementCollector collector = new StatementCollector();
parser.setRDFHandler(collector);
_classUnderTest.service(request, response);
parser.parse(new FileInputStream(tmp), method.getURI().getURI());
assertTrue(!collector.getStatements().isEmpty());
verify(response).setStatus(HttpServletResponse.SC_OK);
servletOutputStream.close();
}
/**
* test get Graph Query.
* @throws Exception The test would fails if Exception occurs
*/
@Test
public void testGraphQuery() throws Exception {
//insert some statments first
for (final String tripleAsString : _data) {
final Statement triple = parseNX(tripleAsString).iterator().next();
TRIPLE_STORE.addData(triple);
}
//test Graph Query
String queryString = "SELECT ?x ?y WHERE { ?x ?p ?y } ";
String uri = BASE_URI + Protocol.REPOSITORIES + "/" + REPO_ID;
File tmp = WebTestUtils.tmpFile();
final ServletOutputStream servletOutputStream = new StubServletOutputStream(tmp);
final HttpServletRequest request = mockHttpRequest(uri, METHOD_POST);
when(request.getContentType()).thenReturn(MIMETYPE_WWW_FORM);
when(request.getParameter(Protocol.QUERY_LANGUAGE_PARAM_NAME)).thenReturn(QueryLanguage.SPARQL.toString());
when(request.getParameter(Protocol.QUERY_PARAM_NAME)).thenReturn(queryString);
when(request.getParameter(Protocol.ACCEPT_PARAM_NAME)).thenReturn("application/x-binary-rdf-results-table");
Vector<String> vec = new Vector<String>();
when(request.getParameterNames()).thenReturn(vec.elements());
when(request.getCharacterEncoding()).thenReturn(UTF_8);
final HttpServletResponse response = mock(HttpServletResponse.class);
when(response.getOutputStream()).thenReturn(servletOutputStream);
_classUnderTest.service(request, response);
Set<TupleQueryResultFormat> tqrFormats = TupleQueryResultParserRegistry.getInstance().getKeys();
TupleQueryResultFormat format = TupleQueryResultFormat.matchMIMEType("application/x-binary-rdf-results-table", tqrFormats);
TupleQueryResultParser parser = QueryResultIO.createParser(format, valueFactory);
FileInputStream in = new FileInputStream(tmp);
BackgroundTupleResult tRes = new BackgroundTupleResult(parser, in, null);
parser.setQueryResultHandler(tRes);
parser.parseQueryResult(in);
assertTrue(tRes.hasNext());
verify(response).setStatus(HttpServletResponse.SC_OK);
servletOutputStream.close();
}
}