package no.priv.garshol.duke.utils; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import no.priv.garshol.duke.DukeException; import no.priv.garshol.duke.StatementHandler; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class NTriplesParserTest { @Test public void testEmpty() throws IOException { List<Statement> model = parse(""); assertTrue("empty data didn't produce empty model", model.isEmpty()); } @Test public void testSingleLine() throws IOException { List<Statement> model = parse("<http://a> <http://b> <http://c> ."); assertEquals(1, model.size()); Statement st = model.get(0); assertEquals("subject", "http://a", st.subject); assertEquals("property", "http://b", st.property); assertEquals("object", "http://c", st.object); assertEquals("literal", false, st.literal); } @Test public void testSingleLineBnode() throws IOException { List<Statement> model = parse("_:a <http://b> <http://c> ."); assertEquals(1, model.size()); Statement st = model.get(0); assertEquals("subject", "_:a", st.subject); assertEquals("property", "http://b", st.property); assertEquals("object", "http://c", st.object); assertEquals("literal", false, st.literal); } @Test public void testTwoLines() throws IOException { List<Statement> model = parse("<http://a> <http://b> <http://c> .\n" + "<http://d> <http://e> <http://f> .\n"); assertEquals(2, model.size()); Statement st = model.get(0); assertEquals("subject", "http://a", st.subject); assertEquals("property", "http://b", st.property); assertEquals("object", "http://c", st.object); assertEquals("literal", false, st.literal); st = model.get(1); assertEquals("subject", "http://d", st.subject); assertEquals("property", "http://e", st.property); assertEquals("object", "http://f", st.object); assertEquals("literal", false, st.literal); } @Test public void testSingleLineLiteral() throws IOException { List<Statement> model = parse("<http://a> <http://b> \"c\" ."); assertEquals(1, model.size()); Statement st = model.get(0); assertEquals("subject", "http://a", st.subject); assertEquals("property", "http://b", st.property); assertEquals("object", "c", st.object); assertEquals("literal", true, st.literal); } @Test public void testLiteralEscaping() throws IOException { List<Statement> model = parse("<http://data.semanticweb.org/person/antonella-poggi> <http://data.semanticweb.org/ns/swc/ontology#affiliation> \"Universita' degli Studi di Roma 'La \\r\\n Sapienza'\" . "); assertEquals(1, model.size()); Statement st = model.get(0); assertEquals("subject", "http://data.semanticweb.org/person/antonella-poggi", st.subject); assertEquals("property", "http://data.semanticweb.org/ns/swc/ontology#affiliation", st.property); assertEquals("object", "Universita' degli Studi di Roma 'La \r\n Sapienza'", st.object); assertEquals("literal", true, st.literal); } @Test public void testComment() throws IOException { List<Statement> model = parse("<http://a> <http://b> <http://c> .\n" + "# this is a comment\n" + "<http://d> <http://e> <http://f> .\n"); assertEquals(2, model.size()); Statement st = model.get(0); assertEquals("subject", "http://a", st.subject); assertEquals("property", "http://b", st.property); assertEquals("object", "http://c", st.object); assertEquals("literal", false, st.literal); st = model.get(1); assertEquals("subject", "http://d", st.subject); assertEquals("property", "http://e", st.property); assertEquals("object", "http://f", st.object); assertEquals("literal", false, st.literal); } @Test public void testLanguageTag() throws IOException { List<Statement> model = parse("<http://a> <http://b> \"foo\"@en ."); assertEquals(1, model.size()); Statement st = model.get(0); assertEquals("subject", "http://a", st.subject); assertEquals("property", "http://b", st.property); assertEquals("object", "foo", st.object); assertEquals("literal", true, st.literal); } @Test public void testLanguageTagLonger() throws IOException { List<Statement> model = parse("<http://a> <http://b> \"foo\"@en-uk ."); assertEquals(1, model.size()); Statement st = model.get(0); assertEquals("subject", "http://a", st.subject); assertEquals("property", "http://b", st.property); assertEquals("object", "foo", st.object); assertEquals("literal", true, st.literal); } @Test public void testLanguageTagBad() throws IOException { try { parse("<http://a> <http://b> \"foo\"@12 ."); fail("bad language tag accepted"); } catch (DukeException e) { // we detected the bad language tag } } @Test public void testLanguageTagBad2() throws IOException { try { parse("<http://a> <http://b> \"foo\"@en-gb-uk ."); fail("bad language tag accepted"); } catch (DukeException e) { // we detected the bad language tag } } @Test public void testDataType() throws IOException { List<Statement> model = parse("<http://a> <http://b> \"1\"^^<http://www.w3.org/2001/XMLSchema#int> ."); assertEquals(1, model.size()); Statement st = model.get(0); assertEquals("subject", "http://a", st.subject); assertEquals("property", "http://b", st.property); assertEquals("object", "1", st.object); assertEquals("literal", true, st.literal); } @Test public void testDataTypeAndLanguageTag() throws IOException { try { parse("<http://a> <http://b> \"1\"^^<http://www.w3.org/2001/XMLSchema#int>@en ."); fail("language tag AND datatype not allowed"); } catch (DukeException e) { // error detected } } @Test public void testLanguageTagAndDataType() throws IOException { try { parse("<http://a> <http://b> \"1\"@en^^<http://www.w3.org/2001/XMLSchema#int> ."); fail("language tag AND datatype not allowed"); } catch (DukeException e) { // error detected } } @Test public void testLiteralEscaping2() throws IOException { String aelig = "\\u" + "00C6"; // doing this to avoid Java parser issues List<Statement> model = parse("<http://data.semanticweb.org/a> <http://data.semanticweb.org/b> \"\\\\\\\"" + aelig + "bing\" . "); assertEquals(1, model.size()); Statement st = model.get(0); assertEquals("subject", "http://data.semanticweb.org/a", st.subject); assertEquals("property", "http://data.semanticweb.org/b", st.property); assertEquals("object", "\\\"\u00C6bing", st.object); assertEquals("literal", true, st.literal); } @Test // checks lower-case letters in escape sequences public void testLiteralEscaping3() throws IOException { String aelig = "\\u" + "00c6"; // doing this to avoid Java parser issues List<Statement> model = parse("<http://data.semanticweb.org/a> <http://data.semanticweb.org/b> \"\\\\\\\"" + aelig + "bing\" . "); assertEquals(1, model.size()); Statement st = model.get(0); assertEquals("subject", "http://data.semanticweb.org/a", st.subject); assertEquals("property", "http://data.semanticweb.org/b", st.property); assertEquals("object", "\\\"\u00C6bing", st.object); assertEquals("literal", true, st.literal); } @Test public void testBlankLine() throws IOException { List<Statement> model = parse("<http://a> <http://b> <http://c> .\n\n" + "<http://d> <http://e> <http://f> .\n"); assertEquals(2, model.size()); Statement st = model.get(0); assertEquals("subject", "http://a", st.subject); assertEquals("property", "http://b", st.property); assertEquals("object", "http://c", st.object); assertEquals("literal", false, st.literal); st = model.get(1); assertEquals("subject", "http://d", st.subject); assertEquals("property", "http://e", st.property); assertEquals("object", "http://f", st.object); assertEquals("literal", false, st.literal); } @Test public void testSingleLineFollowedByGarbage() throws IOException { try { parse("<http://a> <http://b> <http://c> . <http://d> "); fail("parser accepted invalid data"); } catch (DukeException e) { } } @Test public void testLineStops() throws IOException { try { parse("<http://data.mattilsynet.no/sesam/webcruiter/dokument/8865432a-0eec-41e2-a781-992091aba0cc> "); fail("parser accepted invalid data"); } catch (DukeException e) { } } @Test public void testLineStopsBeforeObject() throws IOException { try { parse("<http://data.mattilsynet.no/sesam/webcruiter/dokument/8865432a-0eec-41e2-a781-992091aba0cc> <http://foo> "); fail("parser accepted invalid data"); } catch (DukeException e) { } } @Test public void testLineStopsBeforePeriod() throws IOException { try { parse("<http://data.mattilsynet.no/sesam/webcruiter/dokument/8865432a-0eec-41e2-a781-992091aba0cc> <http://foo> \"2\" "); fail("parser accepted invalid data"); } catch (DukeException e) { } } @Test public void testLineStopsInURI() throws IOException { try { parse("<http://data.mattilsynet.no/sesam/webcruiter/dokument/8865432a-0eec-41e2-a781-992091aba0cc> <http://foo> <http://burrur"); fail("parser accepted invalid data"); } catch (DukeException e) { } } public static List<Statement> parse(String data) throws IOException { StatementBuilder builder = new StatementBuilder(); NTriplesParser.parse(new StringReader(data), builder); return builder.statements; } // --- Recording statement handler static class Statement { String subject; String property; String object; boolean literal; public Statement(String subject, String property, String object, boolean literal) { this.subject = subject; this.property = property; this.object = object; this.literal = literal; } } static class StatementBuilder implements StatementHandler { List<Statement> statements; public StatementBuilder() { this.statements = new ArrayList(); } public void statement(String subject, String property, String object, boolean literal) { statements.add(new Statement(subject, property, object, literal)); } } }