Github user rvesse commented on a diff in the pull request: https://github.com/apache/jena/pull/449#discussion_r207148170 --- Diff: jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java --- @@ -1925,4 +1926,190 @@ public void test_param_string_bug_04() { pss.toString(); } + + @Test + public void test_set_values_item() { + // Tests a single value being added. + String str = "SELECT * WHERE { VALUES ?o {?objs} ?s ?p ?o }"; + ParameterizedSparqlString pss = new ParameterizedSparqlString(str); + pss.setValues("objs", ResourceFactory.createPlainLiteral("test")); + + String exp = "SELECT * WHERE { VALUES ?o {\"test\"} ?s ?p ?o }"; + String res = pss.toString(); + //System.out.println("Exp: " + exp); + //System.out.println("Res: " + res); + Assert.assertEquals(exp, res); + } + + @Test + public void test_set_values_items() { + // Tests two values for same variable. + String str = "SELECT * WHERE { VALUES ?o {?objs} ?s ?p ?o }"; + ParameterizedSparqlString pss = new ParameterizedSparqlString(str); + List<RDFNode> objs = new ArrayList<>(); + objs.add(ResourceFactory.createPlainLiteral("obj_A")); + objs.add(ResourceFactory.createPlainLiteral("obj_B")); + pss.setValues("objs", objs); + + String exp = "SELECT * WHERE { VALUES ?o {\"obj_A\" \"obj_B\"} ?s ?p ?o }"; + String res = pss.toString(); + //System.out.println("Exp: " + exp); + //System.out.println("Res: " + res); + Assert.assertEquals(exp, res); + } + + @Test + public void test_set_values_items_parenthesis() { + // Tests two values for same variable. + String str = "SELECT * WHERE { VALUES (?o) {?objs} ?s ?p ?o }"; + ParameterizedSparqlString pss = new ParameterizedSparqlString(str); + List<RDFNode> objs = new ArrayList<>(); + objs.add(ResourceFactory.createPlainLiteral("obj_A")); + objs.add(ResourceFactory.createPlainLiteral("obj_B")); + pss.setValues("objs", objs); + + String exp = "SELECT * WHERE { VALUES (?o) {(\"obj_A\") (\"obj_B\")} ?s ?p ?o }"; + String res = pss.toString(); + //System.out.println("Exp: " + exp); + //System.out.println("Res: " + res); + Assert.assertEquals(exp, res); + } + + @Test + public void test_set_values_multiple_variables_parenthesis() { + // Tests two values for same variable. + String str = "SELECT * WHERE { VALUES (?p ?o) {?vars} ?s ?p ?o }"; + ParameterizedSparqlString pss = new ParameterizedSparqlString(str); + List<RDFNode> vars = new ArrayList<>(); + vars.add(ResourceFactory.createProperty("http://example.org/prop_A")); + vars.add(ResourceFactory.createPlainLiteral("obj_A")); + pss.setValues("vars", vars); + + String exp = "SELECT * WHERE { VALUES (?p ?o) {(<http://example.org/prop_A> \"obj_A\")} ?s ?p ?o }"; + String res = pss.toString(); + System.out.println("Exp: " + exp); + System.out.println("Res: " + res); + Assert.assertEquals(exp, res); + } + + @Test + public void test_set_values_multi_var() { + // Tests two variables. + String str = "SELECT * WHERE { VALUES ?p {?props} VALUES ?o {?objs} ?s ?p ?o }"; + ParameterizedSparqlString pss = new ParameterizedSparqlString(str); + List<RDFNode> objs = new ArrayList<>(); + objs.add(ResourceFactory.createPlainLiteral("obj_A")); + objs.add(ResourceFactory.createPlainLiteral("obj_B")); + pss.setValues("objs", objs); + + List<RDFNode> props = new ArrayList<>(); + props.add(ResourceFactory.createProperty("http://example.org/prop_A")); + props.add(ResourceFactory.createProperty("http://example.org/prop_B")); + pss.setValues("props", props); + + String exp = "SELECT * WHERE { VALUES ?p {<http://example.org/prop_A> <http://example.org/prop_B>} VALUES ?o {\"obj_A\" \"obj_B\"} ?s ?p ?o }"; + String res = pss.toString(); + //System.out.println("Exp: " + exp); + //System.out.println("Res: " + res); + Assert.assertEquals(exp, res); + } + + @Test + public void test_set_values_multi_var_parenthesis() { + // Tests two variables with parenthesis for one. + String str = "SELECT * WHERE { VALUES (?p) {?props} VALUES ?o {?objs} ?s ?p ?o }"; + ParameterizedSparqlString pss = new ParameterizedSparqlString(str); + List<RDFNode> objs = new ArrayList<>(); + objs.add(ResourceFactory.createPlainLiteral("obj_A")); + objs.add(ResourceFactory.createPlainLiteral("obj_B")); + pss.setValues("objs", objs); + + List<RDFNode> props = new ArrayList<>(); + props.add(ResourceFactory.createProperty("http://example.org/prop_A")); + props.add(ResourceFactory.createProperty("http://example.org/prop_B")); + pss.setValues("props", props); + + String exp = "SELECT * WHERE { VALUES (?p) {(<http://example.org/prop_A>) (<http://example.org/prop_B>)} VALUES ?o {\"obj_A\" \"obj_B\"} ?s ?p ?o }"; + String res = pss.toString(); + //System.out.println("Exp: " + exp); + //System.out.println("Res: " + res); + Assert.assertEquals(exp, res); + } + + @Test + public void test_set_values_grouped_var() { + // Tests two variables with parenthesis for one. + String str = "SELECT * WHERE { VALUES (?p ?o) {?vars} ?s ?p ?o }"; + ParameterizedSparqlString pss = new ParameterizedSparqlString(str); + + List<List<? extends RDFNode>> vars = new ArrayList<>(); + List<RDFNode> objsA = new ArrayList<>(); + objsA.add(ResourceFactory.createProperty("http://example.org/prop_A")); + objsA.add(ResourceFactory.createPlainLiteral("obj_A")); + vars.add(objsA); + + List<RDFNode> objsB = new ArrayList<>(); + objsB.add(ResourceFactory.createProperty("http://example.org/prop_B")); + objsB.add(ResourceFactory.createPlainLiteral("obj_B")); + vars.add(objsB); + + pss.setGroupedValues("vars", vars); + + String exp = "SELECT * WHERE { VALUES (?p ?o) {(<http://example.org/prop_A> \"obj_A\") (<http://example.org/prop_B> \"obj_B\")} ?s ?p ?o }"; + String res = pss.toString(); + //System.out.println("Exp: " + exp); + //System.out.println("Res: " + res); + Assert.assertEquals(exp, res); + } + + @Test(expected = ARQException.class) + public void test_set_values_uri_injection() { + // This injection is prevented by forbidding the > character in URIs + String str = "PREFIX : <http://example/>\nSELECT * WHERE { VALUES ?obj {?objVar} <s> <p> ?obj . }"; + ParameterizedSparqlString pss = new ParameterizedSparqlString(str); + pss.setValues(str, ResourceFactory.createResource("<http://example.org/obj_A>")); + + pss.asQuery(); + Assert.fail("Attempt to do SPARQL injection should result in an exception"); + } + + @Test + public void test_extract_target_vars() { + // Identifies the vars in the VALUES clause according to the substituting varName. + String cmd = "SELECT * WHERE { VALUES ?o {?objs} ?s ?p ?o }"; + String varName = "objs"; + String[] res = ParameterizedSparqlString.extractTargetVars(cmd, varName); + String[] exp = new String[]{"o"}; + + //System.out.println("Exp: " + exp); + //System.out.println("Res: " + res); + Assert.assertArrayEquals(exp, res); + } + + @Test + public void test_extract_two_target_vars() { + // Identifies the vars in the VALUES clause according to the substituting varName. + String cmd = "SELECT * WHERE { VALUES(?p ?o){?vars} ?s ?p ?o }"; + String varName = "vars"; + String[] res = ParameterizedSparqlString.extractTargetVars(cmd, varName); + String[] exp = new String[]{"p", "o"}; + + //System.out.println("Exp: " + exp); + //System.out.println("Res: " + res); + Assert.assertArrayEquals(exp, res); + } + + @Test + public void test_extract_multiple_target_vars() { + // Identifies the vars in the VALUES clause according to the substituting varName. + String cmd = "SELECT * WHERE { VALUES ?p {?props} VALUES ?o {?objs} ?s ?p ?o }"; + String varName = "objs"; + String[] res = ParameterizedSparqlString.extractTargetVars(cmd, varName); + String[] exp = new String[]{"o"}; + + //System.out.println("Exp: " + exp); + //System.out.println("Res: " + res); + Assert.assertArrayEquals(exp, res); + } + --- End diff -- It would be nice to have some negative test cases where the SPARQL string to be substituted into does not correspond correctly to the number of values/variables the user is attempting to set. In particular it isn't clear that the code will do anything sensible if the user calls `setValues()` with a query that never contains the `VALUES` keyword.
---