/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2014. 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.io.IOException;
import com.bigdata.rdf.sparql.ast.eval.ASTConstructIterator;
/**
* This class is concerning the issues raised in trac 804
*
* @see <a href="https://jira.blazegraph.com/browse/BLZG-885" >update bug
* deleting quads</a>
*
* @author jeremycarroll
*/
public class AbstractNamedGraphUpdateTest extends AbstractProtocolTest {
private final static String distinctHintFalse = " hint:Query hint:nativeDistinctSPO false . \n";
private final static String distinctHintTrue = " hint:Query hint:nativeDistinctSPO true . \n";
private final boolean nativeDistinct;
public AbstractNamedGraphUpdateTest(final boolean nativeDistinct, final String name) {
super(name);
this.nativeDistinct = nativeDistinct;
}
private String atomicMoveNamedGraph() {
// Atomic update of uploaded graph - moving eg:tmp to eg:a (deleting old contents of eg:a)
return
"DELETE {\n" +
" GRAPH <eg:a> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
" GRAPH <eg:tmp> {\n" +
" ?news ?newp ?newo\n" +
" }\n" +
"}\n" +
"INSERT {\n" +
" GRAPH <eg:a> {\n" +
" ?news ?newp ?newo\n" +
" }\n" +
"}\n" +
"WHERE {\n" +
distinctHintFalse +
" {\n" +
" GRAPH <eg:a> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
" } UNION {\n" +
" GRAPH <eg:tmp> {\n" +
" ?news ?newp ?newo\n" +
" }\n" +
" }\n" +
"}";
}
private String insertData =
"prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" +
"INSERT DATA\n" +
"{ \n" +
" GRAPH <eg:a> {\n" +
" [ a \"Blank\" ] .\n" +
" <eg:b> rdf:type <eg:c> ; rdf:value [] .\n" +
" [ rdf:value [] ] .\n" +
" }\n" +
" GRAPH <eg:tmp> {\n" +
" [ a \"Blankx\" ] .\n" +
" <eg:B> rdf:type <eg:C> ; rdf:value [] .\n" +
" [ rdf:value [] ] .\n" +
" }\n" +
"}\n";
private void makeUpdate(String update) throws IOException {
final boolean hasHint = update.contains(distinctHintFalse);
if (hasHint) {
ASTConstructIterator.flagToCheckNativeDistinctQuadsInvocationForJUnitTesting = false;
if (nativeDistinct) {
update = update.replace(distinctHintFalse, distinctHintTrue);
}
}
setMethodisPostUrlEncodedData();
serviceRequest("update", update);
if (hasHint) {
assertEquals(nativeDistinct, ASTConstructIterator.flagToCheckNativeDistinctQuadsInvocationForJUnitTesting );
}
}
private void assertQuad(String graph, String triple) throws IOException {
assertQuad("true", graph, triple);
}
private void assertNotQuad(String graph, String triple) throws IOException {
assertQuad("false", graph, triple);
}
void assertQuad(String expected, String graph, String triple) throws IOException {
String result = serviceRequest("query", "ASK { GRAPH " + graph + " { " + triple + "} }" );
assertTrue(result.contains(expected));
}
private void updateAFewTimes(int numberOfUpdatesPerTime) throws IOException {
final int numberOfTimes = 5;
for (int i=0; i<numberOfTimes; i++) {
for (int j=0; j<numberOfUpdatesPerTime;j++) {
makeUpdate(insertData);
}
makeUpdate( atomicMoveNamedGraph() );
assertNotQuad("<eg:tmp>", " ?s ?p ?o ");
}
}
public void test_t_1() throws IOException {
updateAFewTimes(1);
}
public void test_t_2() throws IOException {
updateAFewTimes(2);
}
public void test_t_3() throws IOException {
updateAFewTimes(3);
}
public void test_t_5() throws IOException {
updateAFewTimes(5);
}
public void test_double_triple_delete() throws IOException {
setMethodisPostUrlEncodedData();
makeUpdate("prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" +
"INSERT DATA\n" +
"{ \n" +
" GRAPH <eg:a> {\n" +
" <eg:b> rdf:type <eg:c> \n" +
" }\n" +
" GRAPH <eg:tmp> {\n" +
" <eg:b> rdf:type <eg:c> \n" +
" }\n" +
"}\n");
makeUpdate( "DELETE {\n" +
" GRAPH <eg:a> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
" GRAPH <eg:tmp> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}\n" +
"WHERE {\n" +
distinctHintFalse +
" GRAPH <eg:a> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}");
assertNotQuad("?g","?s ?p ?o");
}
public void test_double_triple_insert() throws IOException {
makeUpdate( "prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" +
"INSERT DATA\n" +
"{ \n" +
" GRAPH <eg:tmp> {\n" +
" <eg:b> rdf:type <eg:c> .\n" +
" <eg:x> rdf:type _:foo \n" +
" }\n" +
"}\n");
makeUpdate( "INSERT {\n" +
" GRAPH <eg:A> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
" GRAPH <eg:B> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}\n" +
"WHERE {\n" +
distinctHintFalse +
" GRAPH <eg:tmp> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}");
assertQuad("<eg:A>","<eg:b> rdf:type <eg:c> ");
assertQuad("<eg:B>","<eg:b> rdf:type <eg:c> ");
assertQuad("<eg:A>","<eg:x> rdf:type ?x");
assertQuad("<eg:B>","<eg:x> rdf:type ?x ");
}
public void test_double_triple_delete_insert() throws IOException {
makeUpdate( "prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" +
"INSERT DATA\n" +
"{ \n" +
" GRAPH <eg:tmp> {\n" +
" <eg:A> <eg:moveTo> <eg:AA> .\n" +
" <eg:B> <eg:moveTo> <eg:BB> \n" +
" }\n" +
"}\n");
makeUpdate( "INSERT {\n" +
" GRAPH <eg:A> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}\n" +
"WHERE {\n" +
" GRAPH <eg:tmp> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}");
makeUpdate( "INSERT {\n" +
" GRAPH <eg:B> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}\n" +
"WHERE {\n" +
" GRAPH <eg:tmp> {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}");
assertQuad("<eg:A>","<eg:A> <eg:moveTo> <eg:AA> ");
assertQuad("<eg:B>","<eg:A> <eg:moveTo> <eg:AA> ");
assertQuad("<eg:A>","<eg:B> <eg:moveTo> <eg:BB>");
assertQuad("<eg:B>","<eg:B> <eg:moveTo> <eg:BB> ");
makeUpdate(
"DELETE {\n" +
" GRAPH ?oldg {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}\n" +
"INSERT {\n" +
" GRAPH ?newg {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}\n" +
"WHERE {\n" +
distinctHintFalse +
" GRAPH <eg:tmp> {\n" +
" ?oldg <eg:moveTo> ?newg\n" +
" }\n" +
" GRAPH ?oldg {\n" +
" ?olds ?oldp ?oldo\n" +
" }\n" +
"}");
assertNotQuad("<eg:A>","<eg:A> <eg:moveTo> <eg:AA> ");
assertNotQuad("<eg:B>","<eg:A> <eg:moveTo> <eg:AA> ");
assertNotQuad("<eg:A>","<eg:B> <eg:moveTo> <eg:BB>");
assertNotQuad("<eg:B>","<eg:B> <eg:moveTo> <eg:BB> ");
assertQuad("<eg:AA>","<eg:A> <eg:moveTo> <eg:AA> ");
assertQuad("<eg:BB>","<eg:A> <eg:moveTo> <eg:AA> ");
assertQuad("<eg:AA>","<eg:B> <eg:moveTo> <eg:BB>");
assertQuad("<eg:BB>","<eg:B> <eg:moveTo> <eg:BB> ");
}
/*
* TODO FIXME - this test is broken when we force it through the
* DELETE+INSERT code path (solution set replay).
*/
// public void test_triple_template_and_fixed_insert() throws IOException {
// makeUpdate( "prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" +
// "INSERT DATA\n" +
// "{ \n" +
// " GRAPH <eg:tmp> {\n" +
// " <eg:b> rdf:type <eg:c> .\n" +
// " }\n" +
// "}\n");
// makeUpdate( "INSERT {\n" +
// " GRAPH <eg:A> {\n" +
// " ?olds ?oldp ?oldo\n" +
// " }\n" +
// " GRAPH <eg:B> {\n" +
// " <eg:b> rdf:type <eg:c> .\n" +
// " }\n" +
// "}\n" +
// "WHERE {\n" +
// distinctHintFalse +
// " GRAPH <eg:tmp> {\n" +
// " ?olds ?oldp ?oldo\n" +
// " }\n" +
// "}");
// assertQuad("<eg:A>","<eg:b> rdf:type <eg:c> ");
// assertQuad("<eg:B>","<eg:b> rdf:type <eg:c> ");
// }
}