Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check minimum table sizes in stream options validator #107

Merged
merged 1 commit into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions core/src/main/scala/eu/ostrzyciel/jelly/core/JellyOptions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ object JellyOptions:
* - version (must be <= Constants.protoVersion and <= supportedOptions.version)
* - generalized statements (must be <= supportedOptions.generalizedStatements)
* - RDF star (must be <= supportedOptions.rdfStar)
* - max name table size (must be <= supportedOptions.maxNameTableSize).
* - max name table size (must be <= supportedOptions.maxNameTableSize and >= 16).
* - max prefix table size (must be <= supportedOptions.maxPrefixTableSize)
* - max datatype table size (must be <= supportedOptions.maxDatatypeTableSize)
* - max datatype table size (must be <= supportedOptions.maxDatatypeTableSize and >= 8)
* - logical stream type (must be compatible with physical stream type and compatible with expected log. stream type)
*
* We don't check:
Expand All @@ -128,23 +128,28 @@ object JellyOptions:
s"This library version supports up to version ${Constants.protoVersion}.")

if requestedOptions.generalizedStatements && !supportedOptions.generalizedStatements then
throw new RdfProtoDeserializationError(s"The stream uses generalized statements, which the user marked as not " +
s"supported. To read this stream, set generalizedStatements to true in the supportedOptions for this decoder.")
throw new RdfProtoDeserializationError(s"The stream uses generalized statements, which are not supported. " +
s"Either disable generalized statements or enable them in the supportedOptions.")

if requestedOptions.rdfStar && !supportedOptions.rdfStar then
throw new RdfProtoDeserializationError(s"The stream uses RDF-star, which the user marked as not supported. " +
s"To read this stream, set rdfStar to true in the supportedOptions for this decoder.")
throw new RdfProtoDeserializationError(s"The stream uses RDF-star, which is not supported. Either disable" +
s" RDF-star or enable it in the supportedOptions.")

def checkTableSize(name: String, size: Int, supportedSize: Int): Unit =
def checkTableSize(name: String, size: Int, supportedSize: Int, minSize: Int = 0): Unit =
if size > supportedSize then
throw new RdfProtoDeserializationError(s"The stream uses a ${name.toLowerCase} table size of $size, which is " +
s"larger than the maximum supported size of $supportedSize. To read this stream, set max${name}TableSize " +
s"to at least $size in the supportedOptions for this decoder."
s"larger than the maximum supported size of $supportedSize."
)
if size < minSize then
throw new RdfProtoDeserializationError(s"The stream uses a ${name.toLowerCase} table size of $size, which is " +
s"smaller than the minimum supported size of $minSize."
)

checkTableSize("Name", requestedOptions.maxNameTableSize, supportedOptions.maxNameTableSize)
// The minimum sizes are hard-coded because it would be impossible to reliably encode the stream
// with smaller tables, especially if RDF-star is used.
checkTableSize("Name", requestedOptions.maxNameTableSize, supportedOptions.maxNameTableSize, 16)
checkTableSize("Prefix", requestedOptions.maxPrefixTableSize, supportedOptions.maxPrefixTableSize)
checkTableSize("Datatype", requestedOptions.maxDatatypeTableSize, supportedOptions.maxDatatypeTableSize)
checkTableSize("Datatype", requestedOptions.maxDatatypeTableSize, supportedOptions.maxDatatypeTableSize, 8)

checkLogicalStreamType(requestedOptions, supportedOptions.logicalType)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -596,4 +596,30 @@ class ProtoDecoderSpec extends AnyWordSpec, Matchers:
error.getMessage should include("datatype table size of 100")
error.getMessage should include("larger than the maximum supported size of 80")
}

"throw exception on a stream with a name table size smaller than supported" in {
val data = wrapEncodedFull(Seq(
JellyOptions.smallGeneralized
.withPhysicalType(streamType)
.withMaxNameTableSize(2) // 16 is the minimum
))
val error = intercept[RdfProtoDeserializationError] {
decoderFactory(None).ingestRow(data.head)
}
error.getMessage should include("name table size of 2")
error.getMessage should include("smaller than the minimum supported size of 16")
}

"throw exception on a stream with a datatype table size smaller than supported" in {
val data = wrapEncodedFull(Seq(
JellyOptions.smallGeneralized
.withPhysicalType(streamType)
.withMaxDatatypeTableSize(2) // 8 is the minimum
))
val error = intercept[RdfProtoDeserializationError] {
decoderFactory(None).ingestRow(data.head)
}
error.getMessage should include("datatype table size of 2")
error.getMessage should include("smaller than the minimum supported size of 8")
}
}