RDF Messages Tests

Living Document,

This version:
https://w3c-cg.github.io/rsp/spec/messages-tests
Issue Tracking:
GitHub
Editors:
Pieter Colpaert
Piotr Sowiński (NeverBlink)

Abstract

Tests for parsers and serializers with message support in various RDF serializations.

1. RDF Messages Interoperability Tests

This document proposes interoperability tests for implementations that support RDF Message Logs for different serializations.

Implementations of parsers and serializers MUST provide conformance tests for RDF Message Logs that verify message-level behavior.

An RDF Message Log parser MUST expose a message-level interface that emits one RDF Dataset per completed message.

A message is completed when a message delimiter or the end of the input is encountered. Empty messages MUST be preserved when they occur before the first triple or quad, or between two delimiters. A trailing delimiter after a non-empty message MUST finalize that message and MUST not by itself create an additional empty trailing message.

Blank node identifiers in RDF Message Logs MUST be scoped to the message in which they occur. Therefore, if the same blank node label appears in two different messages in the same input stream, the parser MUST produce two distinct blank nodes. This requirement applies even when the entire RDF Message Log is parsed from one continuous input string or stream by one parser instance.

Message delimiters are message-level syntax. They MUST only occur where the underlying RDF syntax permits directives or top-level statements, and MUST not occur inside an open graph block. A delimiter encountered inside a graph block MUST be a parse error.

Serializers should produce RDF Message Logs that round-trip to the same message sequence and the same quads per message. Conformance tests should not require a serializer to choose a specific delimiter spelling when more than one delimiter spelling is supported by the target syntax.

1.1. Parsing Tests for Turtle, TriG, N-Triples, and N-Quads

1.1.1. Single Message Without Delimiter

Input:

VERSION "1.2-messages"
<http://example.org/s1> <http://example.org/p> <http://example.org/o1> .

Expected messages:

Message 1:
  <http://example.org/s1> <http://example.org/p> <http://example.org/o1> .

1.1.2. Two Messages With MESSAGE

Input:

VERSION "1.2-messages"
<http://example.org/s1> <http://example.org/p> <http://example.org/o1> .
MESSAGE
<http://example.org/s2> <http://example.org/p> <http://example.org/o2> .

Expected messages:

Message 1:
  <http://example.org/s1> <http://example.org/p> <http://example.org/o1> .

Message 2:
  <http://example.org/s2> <http://example.org/p> <http://example.org/o2> .

1.1.3. Two Messages With @message .

Input:

@version "1.2-messages" .
@prefix ex: <http://example.org/> .

ex:s1 ex:p ex:o1 .
@message .
ex:s2 ex:p ex:o2 .

Expected messages:

Message 1:
  <http://example.org/s1> <http://example.org/p> <http://example.org/o1> .

Message 2:
  <http://example.org/s2> <http://example.org/p> <http://example.org/o2> .

1.1.4. Empty First Message

Input:

VERSION "1.2-messages"
MESSAGE
<http://example.org/s1> <http://example.org/p> <http://example.org/o1> .

Expected messages:

Message 1:
  empty

Message 2:
  <http://example.org/s1> <http://example.org/p> <http://example.org/o1> .

1.1.5. Empty Message Between Non-Empty Messages

Input:

VERSION "1.2-messages"
<http://example.org/s1> <http://example.org/p> <http://example.org/o1> .
MESSAGE
MESSAGE
<http://example.org/s2> <http://example.org/p> <http://example.org/o2> .

Expected messages:

Message 1:
  <http://example.org/s1> <http://example.org/p> <http://example.org/o1> .

Message 2:
  empty

Message 3:
  <http://example.org/s2> <http://example.org/p> <http://example.org/o2> .

1.1.6. Final Delimiter Does Not Create Extra Empty Message

Input:

VERSION "1.2-messages"
<http://example.org/s1> <http://example.org/p> <http://example.org/o1> .
MESSAGE

Expected messages:

Message 1:
  <http://example.org/s1> <http://example.org/p> <http://example.org/o1> .

1.1.7. N-Quads Messages Preserve Graph Names

Input:

VERSION "1.2-messages"
<http://example.org/s1> <http://example.org/p> <http://example.org/o1> <http://example.org/g1> .
MESSAGE
<http://example.org/s2> <http://example.org/p> <http://example.org/o2> <http://example.org/g2> .

Expected messages:

Message 1:
  <http://example.org/s1> <http://example.org/p> <http://example.org/o1> <http://example.org/g1> .

Message 2:
  <http://example.org/s2> <http://example.org/p> <http://example.org/o2> <http://example.org/g2> .

1.1.8. Message With Default Graph And Named Graph Quads

Input:

VERSION "1.2-messages"
PREFIX ex: <http://example.org/>

ex:s1 ex:p ex:o1 .
ex:g {
  ex:s2 ex:p ex:o2 .
  ex:s3 ex:p ex:o3 .
}
MESSAGE
ex:s4 ex:p ex:o4 .

Expected messages:

Message 1:
  <http://example.org/s1> <http://example.org/p> <http://example.org/o1> .
  <http://example.org/s2> <http://example.org/p> <http://example.org/o2> <http://example.org/g> .
  <http://example.org/s3> <http://example.org/p> <http://example.org/o3> <http://example.org/g> .

Message 2:
  <http://example.org/s4> <http://example.org/p> <http://example.org/o4> .

1.1.9. Blank Node Labels Are Scoped Per Message

Input:

VERSION "1.2-messages"
_:b0 <http://example.org/p> <http://example.org/o1> .
MESSAGE
_:b0 <http://example.org/p> <http://example.org/o2> .

Expected result:

Message 1 contains one quad whose subject is a blank node.
Message 2 contains one quad whose subject is a blank node.
The two blank nodes must not be the same RDF term.

This test must be performed on one continuous input string or stream, not by creating two independent parser instances.

1.1.10. Repeated Prefixes Across Messages

Input:

VERSION "1.2-messages"
PREFIX ex: <http://example.org/one/>
ex:s ex:p ex:o .
MESSAGE
PREFIX ex: <http://example.org/two/>
ex:s ex:p ex:o .

Expected messages:

Message 1:
  <http://example.org/one/s> <http://example.org/one/p> <http://example.org/one/o> .

Message 2:
  <http://example.org/two/s> <http://example.org/two/p> <http://example.org/two/o> .

1.1.11. Message Boundary After A Graph Block

Input:

VERSION "1.2-messages"
<http://example.org/g> {
  <http://example.org/a> <http://example.org/b> <http://example.org/c> .
}
MESSAGE
<http://example.org/d> <http://example.org/e> <http://example.org/f> .

Expected messages:

Message 1:
  <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/g> .

Message 2:
  <http://example.org/d> <http://example.org/e> <http://example.org/f> .

1.2. Serialization Tests for Turtle, TriG, N-Triples, and N-Quads

Given a sequence of RDF Messages, a serializer should write a document that can be parsed back into the same sequence of messages and quads.

Serializers may choose the concrete message delimiter supported by their syntax. These tests should not assert whether @message . or MESSAGE was used.

Round-trip input messages:

Message 1:
  <http://example.org/s1> <http://example.org/p> <http://example.org/o1> .

Message 2:
  empty

Message 3:
  <http://example.org/s2> <http://example.org/p> <http://example.org/o2> .

Expected result after serializing and parsing the output:

Message 1:
  <http://example.org/s1> <http://example.org/p> <http://example.org/o1> .

Message 2:
  empty

Message 3:
  <http://example.org/s2> <http://example.org/p> <http://example.org/o2> .

Round-trip input messages with named graph quads:

Message 1:
  <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/g> .

Message 2:
  <http://example.org/d> <http://example.org/e> <http://example.org/f> <http://example.org/g> .

Expected result after serializing and parsing the output:

Message 1:
  <http://example.org/a> <http://example.org/b> <http://example.org/c> <http://example.org/g> .

Message 2:
  <http://example.org/d> <http://example.org/e> <http://example.org/f> <http://example.org/g> .

1.3. Error Tests

1.3.1. Message Delimiter Without Message Support

If a parser is not in RDF Messages mode and encounters a message delimiter, it must reject the document.

Input:

<http://example.org/s> <http://example.org/p> <http://example.org/o> .
MESSAGE

Expected result:

Parse error.

1.3.2. @message Without Trailing Dot

Input:

VERSION "1.2-messages"
<http://example.org/s> <http://example.org/p> <http://example.org/o> .
@message <http://example.org/invalid>

Expected result:

Parse error.

1.3.3. Message Delimiter Inside An Open Graph Block

A message delimiter must not be accepted inside an open graph block. It must be rejected instead of being interpreted as splitting the graph block across two messages.

Input:

VERSION "1.2-messages"
<http://example.org/g> {
  <http://example.org/a> <http://example.org/b> <http://example.org/c> .
MESSAGE
  <http://example.org/d> <http://example.org/e> <http://example.org/f> .
}

Expected result:

Parse error.

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

References

Normative References

[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119