Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.apache.jena.riot.RDFParser
import org.apache.jena.riot.system.StreamRDFLib
import org.apache.jena.sparql.core.Quad

import scala.annotation.tailrec
import scala.util.Using

object RdfValidatePrint extends RdfCommandPrintUtil[RdfFormat.Jena]:
Expand Down Expand Up @@ -91,7 +92,7 @@ object RdfValidate extends JellyCommand[RdfValidateOptions]:
// Step 1: Validate delimiting
validateDelimiting(delimiting, delimited)
// Step 2: Validate basic stream structure & the stream options
val framesSeq = frameIterator.toSeq
val framesSeq = skipEmptyFrames(frameIterator.toSeq)
validateOptions(framesSeq)
// Step 3: Validate the content
validateContent(framesSeq, frameIndices, rdfComparison)
Expand All @@ -109,10 +110,6 @@ object RdfValidate extends JellyCommand[RdfValidateOptions]:
throw CriticalException("Expected undelimited input, but the file was delimited")

private def validateOptions(frames: Seq[RdfStreamFrame]): Unit =
// Validate basic stream structure
if frames.isEmpty then throw CriticalException("Empty input stream")
if frames.head.rows.isEmpty then
throw CriticalException("First frame in the input stream is empty")
if !frames.head.rows.head.row.isOptions then
throw CriticalException("First row in the input stream does not contain stream options")
val streamOptions = frames.head.rows.head.row.options
Expand Down Expand Up @@ -192,6 +189,24 @@ object RdfValidate extends JellyCommand[RdfValidateOptions]:
comparator.compare(rdfComparison, actual)
}

/** Skip empty frames in the stream. If the first frame is empty, we skip it and continue with the
* next one. If the first row is empty, we throw an exception
* @param frames
* frames to check
* @return
* frames after empty frames
*/
@tailrec
private def skipEmptyFrames(
frames: Seq[RdfStreamFrame],
): Seq[RdfStreamFrame] =
if frames.isEmpty then throw CriticalException("Empty input stream")
else if frames.head.rows.isEmpty then
// We want to accept empty frames in the stream, but not empty streams
if frames.tail.isEmpty then throw CriticalException("All frames are empty")
skipEmptyFrames(frames.tail)
else frames

/** Reads the RDF file for comparison and returns a StreamRdfCollector
* @param fileName
* filename to read
Expand Down
Binary file added src/test/resources/firstEmptyFrame.jelly
Binary file not shown.
Binary file added src/test/resources/threeFirstEmptyFrames.jelly
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.scalatest.BeforeAndAfterAll
import org.scalatest.wordspec.AnyWordSpec

import java.io.FileOutputStream
import java.nio.file.{Files, Path}
import java.nio.file.{Files, Path, Paths}
import java.util.UUID.randomUUID
import scala.util.Using

Expand All @@ -24,6 +24,7 @@ trait TestFixtureHelper extends BeforeAndAfterAll:
CliRiot.initialize()
}

private val specificTestDir: Path = Paths.get("src", "test", "resources")
private val tmpDir: Path = Files.createTempDirectory("jelly-cli")

/** The number of triples to generate for the tests
Expand Down Expand Up @@ -85,6 +86,16 @@ trait TestFixtureHelper extends BeforeAndAfterAll:
testCode(tempFile.toString)
} finally { tempFile.toFile.delete() }

def withSpecificJellyFile(
testCode: (String) => Any,
fileName: String,
): Unit = {
val filePath = specificTestDir.resolve(fileName)
if !Files.exists(filePath) then
throw new IllegalArgumentException(s"File $fileName does not exist in $specificTestDir")
else testCode(filePath.toString)
}

def withFullJellyFile(testCode: (String) => Any, frameSize: Int = 256): Unit =
val extension = getFileExtension(JellyLanguage.JELLY)
val tempFile = Files.createTempFile(tmpDir, randomUUID.toString, f".${extension}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,25 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper:
RdfValidate.runTestCommand(List("rdf", "validate"))
}
e.cause.get shouldBe a[CriticalException]
e.cause.get.getMessage should include("First frame in the input stream is empty")
e.cause.get.getMessage should include("All frames are empty")
}

"accept empty frame before stream options" in withSpecificJellyFile(
testCode = { jellyF =>
val (out, err) = RdfValidate.runTestCommand(List("rdf", "validate", jellyF))
out shouldBe empty
},
fileName = "firstEmptyFrame.jelly",
)

"accept three first empty frames" in withSpecificJellyFile(
testCode = { jellyF =>
val (out, err) = RdfValidate.runTestCommand(List("rdf", "validate", jellyF))
out shouldBe empty
},
fileName = "threeFirstEmptyFrames.jelly",
)

"validate delimiting" when {
val frame = RdfStreamFrame(
Seq(
Expand Down