org.trellisldp.io.JenaIOServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for org.trellisldp.io.JenaIOServiceTest.java

Source

/*
 * 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 org.trellisldp.io;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
import static java.util.stream.Stream.of;
import static org.apache.commons.rdf.api.RDFSyntax.JSONLD;
import static org.apache.commons.rdf.api.RDFSyntax.NTRIPLES;
import static org.apache.commons.rdf.api.RDFSyntax.RDFA;
import static org.apache.commons.rdf.api.RDFSyntax.RDFXML;
import static org.apache.commons.rdf.api.RDFSyntax.TURTLE;
import static org.apache.jena.graph.Factory.createDefaultGraph;
import static org.apache.jena.graph.NodeFactory.createBlankNode;
import static org.apache.jena.graph.NodeFactory.createLiteral;
import static org.apache.jena.graph.NodeFactory.createURI;
import static org.apache.jena.graph.Triple.create;
import static org.apache.jena.vocabulary.DCTerms.spatial;
import static org.apache.jena.vocabulary.DCTerms.subject;
import static org.apache.jena.vocabulary.DCTerms.title;
import static org.apache.jena.vocabulary.DCTypes.Text;
import static org.apache.jena.vocabulary.RDF.Nodes.type;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.trellisldp.api.Syntax.LD_PATCH;
import static org.trellisldp.api.Syntax.SPARQL_UPDATE;
import static org.trellisldp.vocabulary.JSONLD.compacted;
import static org.trellisldp.vocabulary.JSONLD.compacted_flattened;
import static org.trellisldp.vocabulary.JSONLD.expanded;
import static org.trellisldp.vocabulary.JSONLD.expanded_flattened;
import static org.trellisldp.vocabulary.JSONLD.flattened;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;

import org.apache.commons.rdf.api.Graph;
import org.apache.commons.rdf.api.RDFSyntax;
import org.apache.commons.rdf.api.RDFTerm;
import org.apache.commons.rdf.api.Triple;
import org.apache.commons.rdf.jena.JenaRDF;
import org.apache.jena.graph.Node;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import org.apache.jena.vocabulary.DCTerms;
import org.apache.jena.vocabulary.RDF;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import org.mockito.Mock;
import org.trellisldp.api.CacheService;
import org.trellisldp.api.IOService;
import org.trellisldp.api.NamespaceService;
import org.trellisldp.api.RDFaWriterService;
import org.trellisldp.api.RuntimeTrellisException;

/**
 * @author acoburn
 */
public class JenaIOServiceTest {

    private static final JenaRDF rdf = new JenaRDF();
    private IOService service, service2, service3;

    @Mock
    private NamespaceService mockNamespaceService;

    @Mock
    private InputStream mockInputStream;

    @Mock
    private OutputStream mockOutputStream;

    @Mock
    private RDFaWriterService mockHtmlSerializer;

    @Mock
    private CacheService<String, String> mockCache;

    @Mock
    private RDFSyntax mockSyntax;

    @BeforeEach
    @SuppressWarnings("unchecked")
    public void setUp() {
        initMocks(this);
        final Map<String, String> namespaces = new HashMap<>();
        namespaces.put("dcterms", DCTerms.NS);
        namespaces.put("rdf", RDF.uri);

        service = new JenaIOService(mockNamespaceService, null, mockCache, "http://www.w3.org/ns/anno.jsonld,,,",
                "http://www.trellisldp.org/ns/");

        service2 = new JenaIOService(mockNamespaceService, mockHtmlSerializer, mockCache, emptySet(),
                singleton("http://www.w3.org/ns/"));

        service3 = new JenaIOService(mockNamespaceService, null, mockCache, emptySet(), emptySet());

        when(mockNamespaceService.getNamespaces()).thenReturn(namespaces);
        when(mockCache.get(anyString(), any(Function.class))).thenAnswer(inv -> {
            final String key = inv.getArgument(0);
            final Function<String, String> mapper = inv.getArgument(1);
            return mapper.apply(key);
        });
    }

    @Test
    public void testJsonLdDefaultSerializer() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service3.write(getTriples(), out, JSONLD);
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service3.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check compact serialization", checkCompactSerialization(output, graph));
    }

    @Test
    public void testJsonLdExpandedSerializer() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, JSONLD, expanded);
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check expanded serialization", checkExpandedSerialization(output, graph));
    }

    @Test
    public void testJsonLdExpandedFlatSerializer() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, JSONLD, expanded, flattened);
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check expanded serialization", checkFlattenedSerialization(output, graph));
    }

    @Test
    public void testJsonLdCustomSerializer() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, JSONLD, rdf.createIRI("http://www.w3.org/ns/anno.jsonld"));
        final String output = out.toString("UTF-8");
        assertTrue(output.contains("\"dcterms:title\":\"A title\""), "missing dcterms:title!");
        assertTrue(output.contains("\"type\":\"Text\""), "missing rdf:type Text!");
        assertTrue(output.contains("\"@context\":"), "missing @context!");
        assertTrue(output.contains("\"@context\":\"http://www.w3.org/ns/anno.jsonld\""),
                "Incorrect @context value!");
        assertFalse(output.contains("\"@graph\":"), "unexpected @graph!");

        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertTrue(validateGraph(graph), "Not all triples present in output graph!");
    }

    @Test
    public void testJsonLdCustomSerializerNoopCache() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        final IOService svc = new JenaIOService(mockNamespaceService, null, new NoopProfileCache(),
                "http://www.w3.org/ns/anno.jsonld,,,", "http://www.trellisldp.org/ns/");

        svc.write(getTriples(), out, JSONLD, rdf.createIRI("http://www.w3.org/ns/anno.jsonld"));
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertTrue(validateGraph(graph), "Not all triples present in output graph!");
    }

    @Test
    public void testJsonLdCustomSerializer2() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service2.write(getTriples(), out, JSONLD, rdf.createIRI("http://www.w3.org/ns/anno.jsonld"));
        final String output = out.toString("UTF-8");
        assertTrue(output.contains("\"dcterms:title\":\"A title\""), "missing/incorrect dcterms:title!");
        assertTrue(output.contains("\"type\":\"Text\""), "missing/incorrect rdf:type!");
        assertTrue(output.contains("\"@context\":"), "missing @context!");
        assertTrue(output.contains("\"@context\":\"http://www.w3.org/ns/anno.jsonld\""),
                "Incorrect @context value!");
        assertFalse(output.contains("\"@graph\":"), "unexpected @graph!");

        final Graph graph = rdf.createGraph();
        service2.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertTrue(validateGraph(graph), "Not all triples present in output graph!");
    }

    @Test
    public void testJsonLdCustomUnrecognizedSerializer() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, JSONLD, rdf.createIRI("http://www.example.org/context.jsonld"));
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check compact serialization", checkCompactSerialization(output, graph));
    }

    @Test
    public void testJsonLdNullCache() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        final IOService myservice = new JenaIOService();
        myservice.write(getTriples(), out, JSONLD, rdf.createIRI("http://www.w3.org/ns/anno.jsonld"));
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        myservice.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check compact serialization", checkCompactSerialization(output, graph));
    }

    @Test
    public void testJsonLdCustomUnrecognizedSerializer2() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service2.write(getTriples(), out, JSONLD, rdf.createIRI("http://www.example.org/context.jsonld"));
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service2.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check compact serialization", checkCompactSerialization(output, graph));
    }

    @Test
    public void testJsonLdCustomUnrecognizedSerializer3() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, JSONLD, rdf.createIRI("http://www.trellisldp.org/ns/nonexistent.jsonld"));
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check compact serialization", checkCompactSerialization(output, graph));
    }

    @Test
    public void testJsonLdCompactedSerializer() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, JSONLD, compacted);
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check compact serialization", checkCompactSerialization(output, graph));
    }

    @Test
    public void testJsonLdFlattenedSerializer() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, JSONLD, flattened);
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check flattened serialization", checkFlattenedSerialization(output, graph));
    }

    @Test
    public void testJsonLdFlattenedSerializer2() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, JSONLD, compacted_flattened);
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check flattened serialization", checkFlattenedSerialization(output, graph));
    }

    @Test
    public void testJsonLdFlattenedSerializer3() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, JSONLD, expanded_flattened);
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check flattened serialization", checkFlattenedSerialization(output, graph));
    }

    @Test
    public void testJsonLdFlattenedSerializer4() throws UnsupportedEncodingException {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, JSONLD, compacted, flattened);
        final String output = out.toString("UTF-8");
        final Graph graph = rdf.createGraph();
        service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), JSONLD, null).forEach(graph::add);
        assertAll("Check flattened serialization", checkFlattenedSerialization(output, graph));
    }

    @Test
    public void testMalformedInput() {
        final ByteArrayInputStream in = new ByteArrayInputStream("<> <ex:test> a Literal\" . ".getBytes(UTF_8));
        assertThrows(RuntimeTrellisException.class, () -> service.read(in, TURTLE, null),
                "No exception on malformed input!");
    }

    @Test
    public void testNTriplesSerializer() {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service3.write(getTriples(), out, NTRIPLES);
        final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        final org.apache.jena.graph.Graph graph = createDefaultGraph();
        RDFDataMgr.read(graph, in, Lang.NTRIPLES);
        assertTrue(validateGraph(rdf.asGraph(graph)), "Failed round-trip for N-Triples!");
    }

    @Test
    public void testBufferedSerializer() {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, RDFXML);
        final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        final org.apache.jena.graph.Graph graph = createDefaultGraph();
        RDFDataMgr.read(graph, in, Lang.RDFXML);
        assertTrue(validateGraph(rdf.asGraph(graph)), "Failed round-trip for RDFXML!");
    }

    @Test
    public void testTurtleSerializer() {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, TURTLE);
        final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        final org.apache.jena.graph.Graph graph = createDefaultGraph();
        RDFDataMgr.read(graph, in, Lang.TURTLE);
        assertTrue(validateGraph(rdf.asGraph(graph)), "Failed round-trip for Turtle!");
    }

    @Test
    public void testTurtleReaderWithContext() {
        final Graph graph = rdf.createGraph();
        service.read(getClass().getResourceAsStream("/testRdf.ttl"), TURTLE, "trellis:data/resource")
                .forEach(graph::add);
        assertTrue(validateGraph(graph), "Failed round-trip for Turtle using a context value!");
    }

    @Test
    public void testHtmlSerializer() throws Exception {
        final IOService service4 = new JenaIOService(mockNamespaceService, mockHtmlSerializer);

        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service4.write(getComplexTriples(), out, RDFA, rdf.createIRI("http://example.org/"));
        verify(mockHtmlSerializer).write(any(), eq(out), eq("http://example.org/"));
    }

    @Test
    public void testHtmlSerializer2() throws Exception {
        final IOService service4 = new JenaIOService(mockNamespaceService, mockHtmlSerializer);

        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service4.write(getComplexTriples(), out, RDFA);
        verify(mockHtmlSerializer).write(any(), eq(out), eq(null));
    }

    @Test
    public void testNullHtmlSerializer() {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        service.write(getTriples(), out, RDFA);
        final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        final org.apache.jena.graph.Graph graph = createDefaultGraph();
        RDFDataMgr.read(graph, in, Lang.TURTLE);
        assertTrue(validateGraph(rdf.asGraph(graph)), "null HTML serialization didn't default to Turtle!");
    }

    @Test
    public void testUpdateError() {
        final Graph graph = rdf.createGraph();
        getTriples().forEach(graph::add);
        assertEquals(3L, graph.size(), "Incorrect graph size!");
        assertThrows(RuntimeTrellisException.class,
                () -> service.update(graph, "blah blah blah blah blah", SPARQL_UPDATE, null),
                "no exception on bad update!");
    }

    @Test
    public void testReadError() throws IOException {
        doThrow(new IOException()).when(mockInputStream).read(any(byte[].class), anyInt(), anyInt());
        assertThrows(RuntimeTrellisException.class, () -> service.read(mockInputStream, TURTLE, "context"),
                "No read exception on bad input stream!");
    }

    @Test
    public void testWriteError() throws IOException {
        doThrow(new IOException()).when(mockOutputStream).write(any(byte[].class), anyInt(), anyInt());
        assertThrows(RuntimeTrellisException.class, () -> service.write(getTriples(), mockOutputStream, TURTLE),
                "No write exception on bad input stream!");
    }

    @Test
    public void testUpdate() {
        final Graph graph = rdf.createGraph();
        getTriples().forEach(graph::add);
        assertEquals(3L, graph.size(), "Incorrect graph size!");
        service.update(graph, "DELETE WHERE { ?s <http://purl.org/dc/terms/title> ?o }", SPARQL_UPDATE,
                "test:info");
        assertEquals(2L, graph.size(), "Incorrect graph size, post update!");
        service.update(graph, "INSERT { " + "<> <http://purl.org/dc/terms/title> \"Other title\" } WHERE {}",
                SPARQL_UPDATE, "trellis:data/resource");
        assertEquals(3L, graph.size(), "Incorrect graph size, after adding triple!");
        service.update(graph,
                "DELETE WHERE { ?s ?p ?o };"
                        + "INSERT { <> <http://purl.org/dc/terms/title> \"Other title\" } WHERE {}",
                SPARQL_UPDATE, "trellis:data/");
        assertEquals(1L, graph.size(), "Incorrect graph size after removing triples!");
        assertEquals("<trellis:data/>",
                graph.stream().findFirst().map(Triple::getSubject).map(RDFTerm::ntriplesString).get(),
                "Incorrect graph subject from updates!");
    }

    @Test
    public void testUpdateInvalidSyntax() {
        final Graph graph = rdf.createGraph();
        getTriples().forEach(graph::add);
        final String patch = "UpdateList <#> <http://example.org/vocab#preferredLanguages> 1..2 ( \"fr\" ) .";
        assertThrows(RuntimeTrellisException.class, () -> service.update(graph, patch, LD_PATCH, null),
                "No exception thrown with invalid update syntax!");
    }

    @Test
    public void testWriteInvalidSyntax() {
        when(mockSyntax.mediaType()).thenReturn("fake/mediatype");

        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        assertThrows(RuntimeTrellisException.class, () -> service.write(getTriples(), out, mockSyntax),
                "No exception thrown with invalid write syntax!");
    }

    @Test
    public void testReadInvalidSyntax() {
        when(mockSyntax.mediaType()).thenReturn("fake/mediatype");
        final String output = "blah blah blah";

        assertThrows(RuntimeTrellisException.class,
                () -> service.read(new ByteArrayInputStream(output.getBytes(UTF_8)), mockSyntax, null),
                "No exception thrown with invalid read syntax!");
    }

    @Test
    public void testReadSyntaxes() {
        assertTrue(service.supportedReadSyntaxes().contains(TURTLE), "Turtle not supported for reading!");
        assertTrue(service.supportedReadSyntaxes().contains(JSONLD), "JSON-LD not supported for reading!");
        assertTrue(service.supportedReadSyntaxes().contains(NTRIPLES), "N-Triples not supported for reading!");
        assertFalse(service.supportedReadSyntaxes().contains(RDFXML),
                "RDF/XML unexpectedly supported for reading!");
        assertFalse(service.supportedReadSyntaxes().contains(RDFA), "RDFa unexpectedly supported for reading!");
        assertTrue(service2.supportedReadSyntaxes().contains(RDFA), "RDFa not supported for reading!");
    }

    @Test
    public void testWriteSyntaxes() {
        assertTrue(service.supportedWriteSyntaxes().contains(TURTLE), "Turtle not supported for writing!");
        assertTrue(service.supportedWriteSyntaxes().contains(JSONLD), "JSON-LD not supported for writing!");
        assertTrue(service.supportedWriteSyntaxes().contains(NTRIPLES), "N-Triples not supported for writing!");
        assertFalse(service.supportedWriteSyntaxes().contains(RDFXML),
                "RDF/XML unexpectedly supported for writing!");
        assertFalse(service.supportedWriteSyntaxes().contains(RDFA), "RDFa unexpectedly supported for writing!");
        assertFalse(service2.supportedWriteSyntaxes().contains(RDFA), "RDFa not supported for writing!");
    }

    @Test
    public void testUpdateSyntaxes() {
        assertTrue(service.supportedUpdateSyntaxes().contains(SPARQL_UPDATE), "SPARQL-Update not supported!");
        assertFalse(service.supportedUpdateSyntaxes().contains(LD_PATCH), "LD-PATCH unexpectedly supported!");
    }

    private static Stream<Triple> getTriples() {
        final Node sub = createURI("trellis:data/resource");
        return of(create(sub, title.asNode(), createLiteral("A title")),
                create(sub, spatial.asNode(), createURI("http://sws.geonames.org/4929022/")),
                create(sub, type, Text.asNode())).map(rdf::asTriple);
    }

    private static Stream<Triple> getComplexTriples() {
        final Node sub = createURI("trellis:data/resource");
        final Node bn = createBlankNode();
        return of(create(sub, title.asNode(), createLiteral("A title")), create(sub, subject.asNode(), bn),
                create(bn, title.asNode(), createLiteral("Other title")),
                create(sub, spatial.asNode(), createURI("http://sws.geonames.org/4929022/")),
                create(sub, type, Text.asNode())).map(rdf::asTriple);

    }

    private static boolean validateGraph(final Graph graph) {
        return getTriples().map(graph::contains).reduce(true, (acc, x) -> acc && x);
    }

    private static Stream<Executable> checkExpandedSerialization(final String serialized, final Graph graph) {
        return of(
                () -> assertTrue(
                        serialized.contains("\"http://purl.org/dc/terms/title\":[{\"@value\":\"A title\"}]"),
                        "no expanded dc:title property!"),
                () -> assertFalse(serialized.contains("\"@context\":"), "unexpected @context!"),
                () -> assertFalse(serialized.contains("\"@graph\":"), "unexpected @graph!"),
                () -> assertTrue(validateGraph(graph), "Not all triples present in output graph!"));
    }

    private static Stream<Executable> checkCompactSerialization(final String serialized, final Graph graph) {
        return of(() -> assertTrue(serialized.contains("\"title\":\"A title\""), "missing/invalid dc:title value!"),
                () -> assertTrue(serialized.contains("\"@context\":"), "missing @context!"),
                () -> assertFalse(serialized.contains("\"@graph\":"), "unexpected @graph!"),
                () -> assertTrue(validateGraph(graph), "Not all triples present in output graph!"));
    }

    private static Stream<Executable> checkFlattenedSerialization(final String serialized, final Graph graph) {
        return of(() -> assertTrue(serialized.contains("\"title\":\"A title\""), "missing/invalid dc:title value!"),
                () -> assertTrue(serialized.contains("\"@context\":"), "missing @context!"),
                () -> assertTrue(serialized.contains("\"@graph\":"), "unexpected @graph!"),
                () -> assertTrue(validateGraph(graph), "Not all triples present in output graph!"));
    }
}