/*
* Copyright 2012 Research Studios Austria Forschungsges.m.b.H.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package won.bot.integrationtest;
import org.apache.jena.query.*;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.vocabulary.RDFS;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import won.bot.PropertyPathConfigurator;
import won.bot.framework.bot.context.CommentBotContextWrapper;
import won.bot.framework.eventbot.event.impl.lifecycle.WorkDoneEvent;
import won.bot.framework.eventbot.listener.impl.ActionOnEventListener;
import won.bot.framework.manager.impl.SpringAwareBotManagerImpl;
import won.bot.impl.CommentBot;
import won.protocol.util.RdfUtils;
import won.protocol.util.linkeddata.CachingLinkedDataSource;
import won.protocol.util.linkeddata.LinkedDataSource;
import won.protocol.vocabulary.WON;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import static junit.framework.Assert.assertEquals;
import static junit.framework.TestCase.assertTrue;
/**
* Integration test.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/spring/app/simpleCommentTest.xml"})
public class CommentBotTest {
private final Logger logger = LoggerFactory.getLogger(getClass());
private static final int RUN_ONCE = 1;
private static final long ACT_LOOP_TIMEOUT_MILLIS = 100;
private static final long ACT_LOOP_INITIAL_DELAY_MILLIS = 100;
private static MyBot bot;
@Autowired
ApplicationContext applicationContext;
@Autowired
SpringAwareBotManagerImpl botManager;
private static boolean run = false;
/**
* This is run before each @TestD method.
*/
@Before
public void before() {
if (!run) {
//create a bot instance and auto-wire it
AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
bot = (MyBot) beanFactory.autowire(MyBot.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
Object botBean = beanFactory.initializeBean(bot, "mybot");
bot = (MyBot) botBean;
//the bot also needs a trigger so its act() method is called regularly.
// (there is no trigger bean in the context)
PeriodicTrigger trigger = new PeriodicTrigger(ACT_LOOP_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
trigger.setInitialDelay(ACT_LOOP_INITIAL_DELAY_MILLIS);
bot.setTrigger(trigger);
logger.info("starting test case testCommentBot");
//adding the bot to the bot manager will cause it to be initialized.
//at that point, the trigger starts.
botManager.addBot(bot);
//the bot should now be running. We have to wait for it to finish before we
//can check the results:
//Together with the barrier.await() in the bot's listener, this trips the barrier
//and both threads continue.
try {
bot.getBarrier().await();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (BrokenBarrierException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
run = true;
}
}
/**
* The main test method.
*
* @throws Exception
*/
@Test
public void testCommentBot() throws Exception {
//now check the results!
bot.executeAsserts();
logger.info("finishing test case testCommentBot");
}
/**
* We create a subclass of the bot we want to test here so that we can
* add a listener to its internal event bus and to access its listeners, which
* record information during the run that we later check with asserts.
*/
public static class MyBot extends CommentBot {
/**
* Used for synchronization with the @TestD method: it should wait at the
* barrier until our bot is done, then execute the asserts.
*/
CyclicBarrier barrier = new CyclicBarrier(2);
private static final String sparqlPrefix =
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>" +
"PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>" +
"PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>" +
"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>" +
"PREFIX won: <http://purl.org/webofneeds/model#>" +
"PREFIX gr: <http://purl.org/goodrelations/v1#>" +
"PREFIX sioc: <http://rdfs.org/sioc/ns#>" +
"PREFIX ldp: <http://www.w3.org/ns/ldp#>";
/**
* Default constructor is required for instantiation through Spring.
*/
public MyBot() {
}
@Override
protected void initializeEventListeners() {
//of course, let the real bot implementation initialize itself
super.initializeEventListeners();
//now, add a listener to the WorkDoneEvent.
//its only purpose is to trip the CyclicBarrier instance that
// the test method is waiting on
getEventBus().subscribe(WorkDoneEvent.class,
new ActionOnEventListener(
getEventListenerContext(),
new TripBarrierAction(getEventListenerContext(), barrier)));
}
public CyclicBarrier getBarrier() {
return barrier;
}
/**
* Here we check the results of the bot's execution.
*/
public void executeAsserts() {
//1 act events
Assert.assertEquals(0, this.needCreator.getExceptionCount());
//1 create need events
Assert.assertEquals(1, this.commentFacetCreator.getEventCount());
Assert.assertEquals(0, this.commentFacetCreator.getExceptionCount());
//1 create comment events
Assert.assertEquals(2, this.needConnector.getEventCount());
Assert.assertEquals(0, this.needConnector.getExceptionCount());
//1 connect, 1 open
Assert.assertEquals(2, this.autoOpener.getEventCount());
Assert.assertEquals(0, this.autoOpener.getExceptionCount());
//10 messages
Assert.assertEquals(1, this.allNeedsDeactivator.getEventCount());
Assert.assertEquals(0, this.allNeedsDeactivator.getExceptionCount());
//4 NeedDeactivated events
Assert.assertEquals(2, this.workDoneSignaller.getEventCount());
Assert.assertEquals(0, this.workDoneSignaller.getExceptionCount());
//TODO: there is more to check:
//* what does the RDF look like?
// --> pull it from the needURI/ConnectionURI and check contents
//* what does the database look like? */
}
@Override
protected void executeAssertionsForEstablishedConnection() {
logger.info("starting test case testCommentRDF");
bot.executeCommentRDFValidationAssert();
}
public void executeCommentRDFValidationAssert() {
List<URI> needs = ((CommentBotContextWrapper) getBotContextWrapper()).getCommentList();
LinkedDataSource linkedDataSource = getEventListenerContext().getLinkedDataSource();
List<URI> properties = new ArrayList<>();
List<URI> objects = new ArrayList<>();
properties.add(URI.create(WON.HAS_CONNECTIONS.getURI()));
//properties.add(RDF.type);
properties.add(URI.create(WON.HAS_REMOTE_CONNECTION.toString()));
properties.add(URI.create(WON.HAS_REMOTE_NEED.toString()));
properties.add(URI.create(RDFS.member.toString()));
List<URI> crawled = new ArrayList<>();
((CachingLinkedDataSource) linkedDataSource).clear();
Dataset dataModel = linkedDataSource.getDataForResourceWithPropertyPath(needs.get(0), PropertyPathConfigurator
.configurePropertyPaths(), 30,
8, true);
logger.debug("crawled dataset with property path: {}", RdfUtils.toString(dataModel));
String queryString = sparqlPrefix +
"SELECT ?need ?connection ?need2 WHERE {" +
//"GRAPH ?g1 {" +
" ?need won:hasConnections ?connections ." +
//"} ." +
//"GRAPH ?g2 {" +
" ?need sioc:hasReply ?need2 ." +
//"} ." +
//"GRAPH ?g3 {" +
"?connections rdfs:member ?connection ." +
//"} ."+
//"Graph ?g4 {" +
"?connection won:hasFacet won:CommentFacet." +
"?connection won:hasRemoteConnection ?connection2." +
"?connection2 won:belongsToNeed ?need2 ." +
//"} ."+
"}";
Query query = QueryFactory.create(queryString);
QueryExecution qExec = QueryExecutionFactory.create(query, dataModel);
ResultSet results = qExec.execSelect();
List<String> actualList = new ArrayList<>();
for (; results.hasNext(); ) {
QuerySolution soln = results.nextSolution();
actualList.add(soln.toString());
RDFNode node = soln.get("?connection");
}
assertEquals("wrong number of results", 1, actualList.size());
qExec.close();
}
public Dataset executeNeedRDFValidationAsserts() {
List<URI> needs = getBotContextWrapper().getNeedCreateList();
Dataset needModel = getEventListenerContext().getLinkedDataSource().getDataForResource(needs.get(0));
System.out.println("executing queries...");
String queryString = sparqlPrefix +
"SELECT ?need WHERE {" +
"?need a won:Need" +
"}";
Query query = QueryFactory.create(queryString);
QueryExecution qExec = QueryExecutionFactory.create(query, needModel);
//ResultSet results = executeQuery(queryString,needModel);
List<String> actualList = new ArrayList<>();
ResultSet results = qExec.execSelect();
for (; results.hasNext(); ) {
QuerySolution soln = results.nextSolution();
actualList.add(soln.toString());
}
assertTrue("wrong number of results", actualList.size() >= 1);
//String expected1 = "( ?event = <" + EXAMPLE_ONTOLOGY_URI + "Open_01_1> ) ( ?eventType = <" + WON_ONTOLOGY_URI + "Open> )";
//assertThat(actualList, hasItems(expected1));
return needModel;
}
public Dataset executeCommentRDFValidationAsserts() {
List<URI> needs = ((CommentBotContextWrapper) getBotContextWrapper()).getCommentList();
Dataset commentModel = getEventListenerContext().getLinkedDataSource().getDataForResource(needs.get(0));
System.out.println("executing queries...");
String queryString = sparqlPrefix +
"SELECT ?need WHERE {" +
"?need a won:Need." +
"?need won:hasFacet won:CommentFacet" +
"}";
Query query = QueryFactory.create(queryString);
QueryExecution qExec = QueryExecutionFactory.create(query, commentModel);
List<String> actualList = new ArrayList<>();
try {
ResultSet results = qExec.execSelect();
for (; results.hasNext(); ) {
QuerySolution soln = results.nextSolution();
actualList.add(soln.toString());
}
} finally {
qExec.close();
}
assertTrue("wrong number of results", actualList.size() >= 1);
return commentModel;
}
public void executeNeedCommentConnectionRDFValidationAsserts(Model needModel, Model commentModel) {
System.out.println("executing queries...");
String queryString = sparqlPrefix +
"SELECT ?need ?connection ?state WHERE {" +
"?need won:hasConnections ?connections." +
"?connections rdfs:member ?connection." +
"?connection won:hasConnectionState ?state." +
"}";
logger.debug(RdfUtils.toString(needModel));
Dataset dataset = null;
//Query query = queryString.asQuery();
//QueryExecution qExec = QueryExecutionFactory.create(query, dataset);
Query query = QueryFactory.create(queryString);
QueryExecution qExec = QueryExecutionFactory.create(query, commentModel);
// Query query = QueryFactory.create(queryString);
// QueryExecution qExec = QueryExecutionFactory.create(query, dsARQ);
ResultSet results = qExec.execSelect();
// ResultSet results = executeQuery(queryString,needModel);
URI needConnectionCollectionURI = null;
URI needConnectionURI = null;
URI commentConnectionsURI = null;
URI needConnectionURICheck = null;
List<String> actualList = new ArrayList<>();
for (; results.hasNext(); ) {
QuerySolution soln = results.nextSolution();
actualList.add(soln.toString());
RDFNode node = soln.get("?connections");
String nodeStr = node.toString();
needConnectionCollectionURI = URI.create(nodeStr);
}
qExec.close();
assertTrue("wrong number of results", actualList.size() >= 1);
Dataset needConnections = getEventListenerContext().getLinkedDataSource().getDataForResource(
needConnectionCollectionURI);
String queryString2 = sparqlPrefix +
"SELECT ?connection WHERE {" +
"?connections rdfs:member ?connection" +
"}";
logger.debug(RdfUtils.toString(needConnections));
Query query2 = QueryFactory.create(queryString2);
QueryExecution qExec2 = QueryExecutionFactory.create(query2, needConnections);
ResultSet results2 = qExec2.execSelect();
//ResultSet results2 = executeQuery(queryString2, needConnections);
List<String> actualList2 = new ArrayList<>();
for (; results2.hasNext(); ) {
QuerySolution soln = results2.nextSolution();
actualList2.add(soln.toString());
RDFNode node = soln.get("?connection");
String nodeStr = node.toString();
needConnectionURI = URI.create(nodeStr);
}
qExec2.close();
assertTrue("wrong number of results", actualList2.size() >= 1);
Dataset needConnection = getEventListenerContext().getLinkedDataSource().getDataForResource(needConnectionURI);
String queryString3 = sparqlPrefix +
"SELECT ?remoteConnection WHERE {" +
"?connection won:hasRemoteConnection ?remoteConnection" +
"}";
logger.debug(RdfUtils.toString(needConnection));
Query query3 = QueryFactory.create(queryString3);
QueryExecution qExec3 = QueryExecutionFactory.create(query3, needConnection);
ResultSet results3 = qExec3.execSelect();
List<String> actualList3 = new ArrayList<>();
for (; results3.hasNext(); ) {
QuerySolution soln = results3.nextSolution();
actualList3.add(soln.toString());
RDFNode node = soln.get("?remoteConnection");
String nodeStr = node.toString();
commentConnectionsURI = URI.create(nodeStr);
}
assertTrue("wrong number of results", actualList3.size() >= 1);
Dataset remoteConnections = getEventListenerContext().getLinkedDataSource().getDataForResource(
commentConnectionsURI);
String queryString4 = sparqlPrefix +
"SELECT ?remoteConnection WHERE {" +
"?connection won:hasRemoteConnection ?remoteConnection" +
"}";
logger.debug(RdfUtils.toString(remoteConnections));
// ResultSet results3 = executeQuery(queryString2, needConnections);
Query query4 = QueryFactory.create(queryString4);
QueryExecution qExec4 = QueryExecutionFactory.create(query4, remoteConnections);
ResultSet results4 = qExec4.execSelect();
List<String> actualList4 = new ArrayList<>();
for (; results4.hasNext(); ) {
QuerySolution soln = results4.nextSolution();
actualList4.add(soln.toString());
RDFNode node = soln.get("?remoteConnection");
String nodeStr = node.toString();
needConnectionURICheck = URI.create(nodeStr);
}
qExec4.close();
assertTrue("wrong number of results", actualList4.size() >= 1);
assertEquals(needConnectionURI, needConnectionURICheck);
}
public ResultSet executeQuery(String queryString, Model model) {
Query query = QueryFactory.create(queryString);
QueryExecution qExec = QueryExecutionFactory.create(query, model);
ResultSet results;
try {
results = qExec.execSelect();
} finally {
qExec.close();
}
return results;
}
}
}