From 343757e71ff21cf92192147c136a8cc615f273b8 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Thu, 19 Nov 2020 23:06:05 +0000 Subject: Add wrapper class for (boolean) conjunctive queries --- .../ac/ox/cs/rsacomb/FilteringProgramSpecs.scala | 85 -------- .../sparql/ConjunctiveQueryAnswerSpecs.scala | 62 ++++++ .../cs/rsacomb/sparql/ConjunctiveQuerySpec.scala | 235 +++++++++++++++++++++ 3 files changed, 297 insertions(+), 85 deletions(-) create mode 100644 src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQueryAnswerSpecs.scala create mode 100644 src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQuerySpec.scala (limited to 'src/test/scala/uk/ac/ox/cs') diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala index 49abd48..e9a20db 100644 --- a/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala @@ -310,89 +310,4 @@ class FilteringProgramSpec import FilteringProgramSpec._ - "Queries" should "have distinct answer and bounded variables" in { - for (query <- queries) { - val program = new FilteringProgram(query, List()) - forAll(program.answer) { v => program.bounded should not contain v } - forAll(program.bounded) { v => program.answer should not contain v } - } - } - - "Query 0" should "have {?obj, ?pred} as bounded variables" in { - val pred = Variable.create("obj") - val obj = Variable.create("pred") - val program = new FilteringProgram(query0, List()) - program.bounded should contain theSameElementsAs List(pred, obj) - } - - "Query 1" should "have no bounded variable" in { - val program = new FilteringProgram(query1, List()) - program.bounded shouldBe empty - } - - "Query 2" should "have no bounded variable" in { - val program = new FilteringProgram(query2, List()) - program.bounded shouldBe empty - } - - "Query 3" should "have {?w, ?fp} as bounded variables" in { - val w = Variable.create("w") - val fp = Variable.create("fp") - val program = new FilteringProgram(query3, List()) - program.bounded should contain theSameElementsAs List(w, fp) - } - - "Query 4" should "have no bounded variable" in { - val program = new FilteringProgram(query4, List()) - program.bounded shouldBe empty - } - - "Query 5" should "have a non-empty bounded set" in { - val w = Variable.create("w") - val c_int = Variable.create("c_int") - val f_int = Variable.create("f_int") - val c_unit = Variable.create("c_unit") - val program = new FilteringProgram(query5, List()) - program.bounded should contain theSameElementsAs List( - w, - c_int, - f_int, - c_unit - ) - } - - "Query 6" should "have a non-empty bounded set" in { - val w = Variable.create("w") - val int = Variable.create("int") - val program = new FilteringProgram(query6, List()) - program.bounded should contain theSameElementsAs List(w, int) - } - - "Query 7" should "have a non-empty bounded set" in { - val w = Variable.create("w") - val z = Variable.create("z") - val u = Variable.create("u") - val strat_unit_name = Variable.create("strat_unit_name") - val wellbore = Variable.create("wellbore") - val cored_int = Variable.create("cored_int") - val c = Variable.create("c") - val sample_depth = Variable.create("sample_depth") - val p = Variable.create("p") - val top = Variable.create("top") - val bot = Variable.create("bot") - val program = new FilteringProgram(query7, List()) - program.bounded should contain theSameElementsAs List( - w, - z, - u, - strat_unit_name, - wellbore, - cored_int, - c, - sample_depth, - p, - top, - bot - ) - } } diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQueryAnswerSpecs.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQueryAnswerSpecs.scala new file mode 100644 index 0000000..65c3e29 --- /dev/null +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQueryAnswerSpecs.scala @@ -0,0 +1,62 @@ +package uk.ac.ox.cs.rsacomb.sparql + +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers +import tech.oxfordsemantic.jrdfox.logic.expression.IRI + +object ConjunctiveQueryAnswerSpec { + + val iri1 = IRI.create("_:iri1") + val iri2 = IRI.create("_:iri2") + val iri3 = IRI.create("_:iri3") + + val oneAnswer = new ConjunctiveQueryAnswers(false, Seq(Seq(iri1, iri2, iri3))) + val multipleAnswers = + new ConjunctiveQueryAnswers( + false, + Seq(Seq(iri1, iri1), Seq(iri1, iri2), Seq(iri1, iri3)) + ) + val noAnswer = new ConjunctiveQueryAnswers(false, Seq()) + val emptyAnswer = new ConjunctiveQueryAnswers(false, Seq(Seq())) + + val falseAnswer = new ConjunctiveQueryAnswers(true, Seq()) + val trueAnswer1 = new ConjunctiveQueryAnswers(true, Seq(Seq())) + val trueAnswer2 = + new ConjunctiveQueryAnswers( + true, + Seq(Seq(iri1, iri1), Seq(iri1, iri2), Seq(iri1, iri3)) + ) +} + +class ConjunctiveQueryAnswerSpec extends AnyFlatSpec with Matchers { + + import ConjunctiveQueryAnswerSpec._ + + "A conjunctive query" should "print a single line if it has a single answer" in { + oneAnswer.toString shouldBe s"($iri1, $iri2, $iri3)" + } + + it should "print multiple answers on multiple lines" in { + multipleAnswers.toString shouldBe s"($iri1, $iri1)\n($iri1, $iri2)\n($iri1, $iri3)" + } + + it should "print a special \"NO ANSWER\" string when it has no answer" in { + noAnswer.toString shouldBe "NO ANSWER" + } + + it should "print an empty list when it has an empty answer" in { + emptyAnswer.toString shouldBe "()" + } + + "A boolean conjunctive query" should "print \"FALSE\" when it has no answer" in { + falseAnswer.toString shouldBe "FALSE" + } + + it should "print \"TRUE\" when it has a single empty answer" in { + trueAnswer1.toString shouldBe "TRUE" + } + + it should "print \"TRUE\" when it has a non-empty collection of answers" in { + trueAnswer2.toString shouldBe "TRUE" + } +} diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQuerySpec.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQuerySpec.scala new file mode 100644 index 0000000..e683d36 --- /dev/null +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/sparql/ConjunctiveQuerySpec.scala @@ -0,0 +1,235 @@ +package uk.ac.ox.cs.rsacomb.sparql + +import org.scalatest.{Inspectors, OptionValues} +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers +import tech.oxfordsemantic.jrdfox.logic.expression.Variable + +object ConjunctiveQuerySpec { + + val cq0 = """ + PREFIX : + + SELECT ?X + WHERE { + ?X a :D ; + :R ?Y . + ?Y :S ?Z . + ?Z a :D . + } + """ + + val cq1 = """ + PREFIX : + + SELECT * + WHERE { + ?X a :D ; + :R ?Y . + ?Y :S ?Z . + ?Z a :D . + } + """ + + val cq2 = """ + PREFIX : + SELECT * + WHERE { + ?w a :Wellbore ; + :wellboreDocument ?doc . + ?doc :hasURL ?document_hyperlink + } + """ + + val cq3 = """ + PREFIX : + SELECT ?wellbore ?formation_pressure + WHERE { + ?w a :Wellbore ; + :name ?wellbore ; + :hasFormationPressure ?fp . + ?fp :valueInStandardUnit ?formation_pressure + } + """ + + val cq4 = """ + PREFIX : + SELECT * + WHERE { + ?w a :Wellbore ; + :hasGeochemicalMeasurement ?measurement . + ?measurement :cgType ?cgtype ; + :peakName ?peakType ; + :peakHeight ?peak_height ; + :peakAmount ?peak_amount + } + """ + + val cq5 = """ + PREFIX : + SELECT ?wellbore ?unit_name ?discovery + WHERE { + ?w a :Wellbore ; + :name ?wellbore ; + :hasWellboreInterval ?c_int ; + :hasWellboreInterval ?f_int . + ?c_int :hasUnit ?c_unit . + ?c_unit :name ?unit_name . + ?f_int a :FluidZone ; + :name ?discovery ; + :overlapsWellboreInterval ?c_int + } + """ + + val cq6 = """ + PREFIX : + SELECT DISTINCT ?wellbore ?content + WHERE { + ?w a :Wellbore ; + :name ?wellbore ; + :hasWellboreInterval ?int . + ?int a :FluidZone ; + :fluidZoneContent ?content + } + """ + + val cq7 = """ + PREFIX : + SELECT ?wName ?sample ?porosity ?top_depth_md ?bot_depth_md + WHERE { + ?w a :Wellbore ; + :name ?wName ; + :hasWellboreInterval ?z . + ?z :hasUnit ?u . + ?u :name ?strat_unit_name . + ?wellbore :hasWellboreInterval ?cored_int . + ?c :extractedFrom ?cored_int ; + :hasCoreSample ?sample . + ?sample :hasDepth ?sample_depth . + ?sample_depth + :inWellboreInterval ?z . + ?sample :hasPorosity ?p . + ?p :valueInStandardUnit ?porosity . + ?z :hasTopDepth ?top . + ?top a :MeasuredDepth ; + :valueInStandardUnit ?top_depth_md . + ?z :hasBottomDepth ?bot . + ?bot a :MeasuredDepth ; + :valueInStandardUnit ?bot_depth_md + } + """ + + val bcq0 = """ + PREFIX : + ASK { + :turk a :Doctor ; + :married ?X . + ?X a :Nurse . + } + """ + + val queries = + List(cq0, cq1, cq2, cq3, cq4, cq5, cq6, cq7, bcq0) + +} + +class ConjunctiveQuerySpec + extends AnyFlatSpec + with Matchers + with Inspectors + with OptionValues { + + import ConjunctiveQuerySpec._ + + "A conjunctive query" should "result in a `ConjunctiveQuery` instance" in { + ConjunctiveQuery(cq0) shouldBe defined + } + + "A boolean conjunctive query" should "result in a `ConjunctiveQuery` instance" in { + ConjunctiveQuery(bcq0) shouldBe defined + } + + "A query with proper SELECT defined" should "not be a BCQ" in { + ConjunctiveQuery(cq0).value should not be 'boolean + } + + "A query with a \"*\" SELECT" should "not be a BCQ" in { + ConjunctiveQuery(cq1).value should not be 'boolean + } + + "An ASK query" should "not be a BCQ" in { + ConjunctiveQuery(bcq0).value shouldBe 'boolean + } + + "Queries" should "have distinct answer and bounded variables" in { + for (q <- queries) { + val cq = ConjunctiveQuery(q) + forAll(cq.value.answer) { v => cq.value.bounded should not contain v } + forAll(cq.value.bounded) { v => cq.value.answer should not contain v } + } + } + + "CQ0" should "have {?obj, ?pred} as bounded variables" in { + ConjunctiveQuery(cq0).value.bounded should contain theSameElementsAs + List( + Variable.create("Y"), + Variable.create("Z") + ) + } + + "CQ1" should "have no bounded variable" in { + ConjunctiveQuery(cq1).value.bounded shouldBe empty + } + + "CQ2" should "have no bounded variable" in { + ConjunctiveQuery(cq2).value.bounded shouldBe empty + } + + "CQ3" should "have {?w, ?fp} as bounded variables" in { + ConjunctiveQuery(cq3).value.bounded should contain theSameElementsAs + List( + Variable.create("w"), + Variable.create("fp") + ) + } + + "CQ4" should "have no bounded variable" in { + ConjunctiveQuery(cq4).value.bounded shouldBe empty + } + + "CQ5" should "have a non-empty bounded set" in { + ConjunctiveQuery(cq5).value.bounded should contain theSameElementsAs + List( + Variable.create("w"), + Variable.create("c_int"), + Variable.create("f_int"), + Variable.create("c_unit") + ) + } + + "CQ6" should "have a non-empty bounded set" in { + ConjunctiveQuery(cq6).value.bounded should contain theSameElementsAs + List( + Variable.create("w"), + Variable.create("int") + ) + } + + "CQ7" should "have a non-empty bounded set" in { + ConjunctiveQuery(cq7).value.bounded should contain theSameElementsAs + List( + Variable.create("w"), + Variable.create("z"), + Variable.create("u"), + Variable.create("strat_unit_name"), + Variable.create("wellbore"), + Variable.create("cored_int"), + Variable.create("c"), + Variable.create("sample_depth"), + Variable.create("p"), + Variable.create("top"), + Variable.create("bot") + ) + } + +} -- cgit v1.2.3